title: Is Rfc2898DeriveBytes equivalent to PKCS5_PBKDF2_HMAC_SHA1?
body: <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>