Note that there are some explanatory texts on larger screens.

plurals
  1. POIs Rfc2898DeriveBytes equivalent to PKCS5_PBKDF2_HMAC_SHA1?
    text
    copied!<p>Rfc2898DeriveBytes in c# and PKCS5_PBKDF2_HMAC_SHA1 in C++ are supposed to be the same function (<a href="http://en.wikipedia.org/wiki/PBKDF2" rel="nofollow">PBKDF2</a>). but when I tried to encrypt a message in c# and decrypt it in c++, the password comes out different. I am putting the same information (passphrase, IV,and salt) in both sides. I have compiled some simpler examples to show what is going on. Am I making a mistake, or do I need to use a different library somewhere?</p> <p>c# encryption:</p> <pre><code>using System; using System.IO; using System.Text; using System.Security.Cryptography; public class RijndaelSimpleTest { [STAThread] static void Main(string[] args) { string plainText = "Hello, World!"; string passPhrase = "testtesttesttesttesttest"; string initVector = "6543210987654321"; string saltValue = "1234567890123456"; int passwordIterations = 10000; int keySize = 32; byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue); byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector); byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText); Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passPhrase, saltValueBytes, passwordIterations); byte[] keyBytes = password.GetBytes(keySize); string debugPassword = Convert.ToBase64String(keyBytes); RijndaelManaged symmetricKey = new RijndaelManaged(); symmetricKey.Mode = CipherMode.CBC; ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes); MemoryStream memoryStream = new MemoryStream(); CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write); cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length); cryptoStream.FlushFinalBlock(); byte[] cipherTextBytes = memoryStream.ToArray(); memoryStream.Close(); cryptoStream.Close(); string encyptText = Convert.ToBase64String(cipherTextBytes); string cipherText = initVector + saltValue + encyptText; Console.WriteLine(String.Format("Plaintext : {0}", plainText)); Console.WriteLine(String.Format("passPhrase : {0}", passPhrase)); Console.WriteLine(String.Format("initVector : {0}", initVector)); Console.WriteLine(String.Format("saltValue : {0}", saltValue)); Console.WriteLine(String.Format("passwordIterations : {0}", passwordIterations)); Console.WriteLine(String.Format("keySize : {0}", keySize)); Console.WriteLine(String.Format("password : {0}", debugPassword)); Console.WriteLine(String.Format("EncryptedText : {0}", encyptText)); Console.WriteLine(String.Format("EncryptedText+IV+SALT : {0}", cipherText)); } } </code></pre> <p>Outputs</p> <pre><code>Plaintext : Hello, World! passPhrase : testtesttesttesttesttest initVector : 6543210987654321 saltValue : 1234567890123456 passwordIterations : 10000 keySize : 32 password : uu1FmPoEROlTBOvilXnIHG64uS56i3f4br/RZ1d49YE= EncryptedText : rVGIwm/WH9tw/SiN+iXw0Q== EncryptedText+IV+SALT : 65432109876543211234567890123456rVGIwm/WH9tw/SiN+iXw0Q== </code></pre> <p>c++ Output:</p> <pre><code>#include &lt;openssl/evp.h&gt; #include &lt;openssl/aes.h&gt; #include &lt;stdio.h&gt; #include &lt;string&gt; #include &lt;iostream&gt; const unsigned char* convertString(const std::string&amp; s){ unsigned char * bytes = new unsigned char[s.size() + 1]; std::copy(s.begin(), s.end(), bytes); bytes[s.size()] = '\0'; return(bytes); } int main(int argc, char** argv) { const char passPhrase[] = "testtesttesttesttesttest"; std::string ExpectedPlaintext = "Hello, World!"; int passwordIterations = 10000; int keySize = 32; std::string EncryptedText = "65432109876543211234567890123456rVGIwm/WH9tw/SiN+iXw0Q=="; std::string ExpectedIV = "6543210987654321"; std::string ExpectedSalt = "1234567890123456"; std::string ExpectedCipherText = "rVGIwm/WH9tw/SiN+iXw0Q=="; std::string Expectedpassword = "uu1FmPoEROlTBOvilXnIHG64uS56i3f4br/RZ1d49YE="; const unsigned char *initVector = convertString(EncryptedText.substr(0,16)); const unsigned char *saltValue = convertString(EncryptedText.substr(16,16)); const unsigned char *ciphertext = convertString(EncryptedText.substr(16+16)); unsigned char password[keySize+16+1]; if (PKCS5_PBKDF2_HMAC_SHA1(passPhrase, strlen(passPhrase), saltValue, strlen((char*)saltValue), passwordIterations, keySize+16, password) != 1) { std::cout &lt;&lt; "Could not derive password" &lt;&lt; std::endl; return -1; } password[keySize] = '\0'; int p_len = keySize; int f_len = 0; unsigned char *plaintext = (unsigned char*)malloc(p_len + AES_BLOCK_SIZE); EVP_CIPHER_CTX d_ctx; EVP_CIPHER_CTX_init(&amp;d_ctx); EVP_DecryptInit_ex(&amp;d_ctx, EVP_aes_256_cbc(), NULL, password, initVector); EVP_DecryptInit_ex (&amp;d_ctx, NULL, NULL, NULL, NULL); EVP_DecryptUpdate (&amp;d_ctx, plaintext, &amp;p_len, ciphertext, keySize); EVP_DecryptFinal_ex(&amp;d_ctx, plaintext+p_len, &amp;f_len); keySize = p_len + f_len; std::cout &lt;&lt; "EncryptedText : " &lt;&lt; EncryptedText &lt;&lt; std::endl; std::cout &lt;&lt; "passPhrase : " &lt;&lt; passPhrase &lt;&lt; std::endl; std::cout &lt;&lt; "passwordIterations: " &lt;&lt; passwordIterations &lt;&lt; std::endl; std::cout &lt;&lt; "keySize : " &lt;&lt; keySize &lt;&lt; std::endl; std::cout &lt;&lt; "ExpectedIV : " &lt;&lt; ExpectedIV &lt;&lt; std::endl; std::cout &lt;&lt; "initVector : " &lt;&lt; initVector &lt;&lt; std::endl; std::cout &lt;&lt; "ExpectedSalt : " &lt;&lt; ExpectedSalt &lt;&lt; std::endl; std::cout &lt;&lt; "saltValue : " &lt;&lt; saltValue &lt;&lt; std::endl; std::cout &lt;&lt; "ExpectedCipherText: " &lt;&lt; ExpectedCipherText &lt;&lt; std::endl; std::cout &lt;&lt; "ciphertext : " &lt;&lt; ciphertext &lt;&lt; std::endl; std::cout &lt;&lt; "Expectedpassword : " &lt;&lt; Expectedpassword &lt;&lt; std::endl; std::cout &lt;&lt; "password : " &lt;&lt; password &lt;&lt; std::endl; std::cout &lt;&lt; "ExpectedPlaintext : " &lt;&lt; ExpectedPlaintext &lt;&lt; std::endl; std::cout &lt;&lt; "plaintext : " &lt;&lt; plaintext &lt;&lt; std::endl; EVP_CIPHER_CTX_cleanup(&amp;d_ctx); delete[] plaintext; delete[] initVector; delete[] saltValue; delete[] ciphertext; return 0; } </code></pre> <p>Which outputs:</p> <pre><code>EncryptedText : 65432109876543211234567890123456rVGIwm/WH9tw/SiN+iXw0Q== passPhrase : testtesttesttesttesttest passwordIterations: 10000 keySize : 16 ExpectedIV : 6543210987654321 initVector : 6543210987654321 ExpectedSalt : 1234567890123456 saltValue : 1234567890123456 ExpectedCipherText: rVGIwm/WH9tw/SiN+iXw0Q== ciphertext : rVGIwm/WH9tw/SiN+iXw0Q== Expectedpassword : uu1FmPoEROlTBOvilXnIHG64uS56i3f4br/RZ1d49YE= password : ºíEúDéSëâyÈn¸¹.zwøn¿ÑgWxõ ExpectedPlaintext : Hello, World! plaintext : ÊÁMþ±B¯ÍN'¤ä+èû~OÂ(H¢ </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload