title: Decrypt string in C# that was encrypted with PHP openssl_encrypt
body: <p>I have a customer encrypting a string in PHP with the following code:</p>
  
  <pre><code>    $password = 'Ty63rs4aVqcnh2vUqRJTbNT26caRZJ';
      $method = 'AES-256-CBC';
      texteACrypter = 'Whether you think you can, or you think you can\'t--you\'re right. - Henry Ford';
  
      $encrypted = openssl_encrypt($texteACrypter, $method, $password);
  </code></pre>
  
  <p>which results in this encrypted output: <code>MzVWX4tH4yZWc/w75zUagUMEsP34ywSYISsIIS9fj0W3Q/lR0hBrHmdvMOt106PlKhN/1zXFBPbyKmI6nWC5BN54GuGFSjkxfuansJkfoi0=</code></p>
  
  <p>When I try to decrypt that string in C# it gives me a bunch of junk like so: <code>Z�o�}'*2��I4y�J6S��
  ��xz���{9^�ED�fF
  �}��گs�)�Q���i��$)�</code></p>
  
  <p>I have tried changing the padding, using AesManaged instead of RijndaelManaged, changing the keysize, using a different key, etc. All result in either different junk strings or various exceptions. I must be missing something really basic here but I'm not sure what else to try at this point.</p>
  
  <p>Here is my decryption code (that I shamelessly copied from another stackoverflow question: <a href="https://stackoverflow.com/questions/5452422/openssl-using-only-net-classes">openssl using only .NET classes</a>)</p>
  
  <pre><code>class Program
  {
      //https://stackoverflow.com/questions/5452422/openssl-using-only-net-classes
      static void Main(string[] args)
      {
          var secret = "Ty63rs4aVqcnh2vUqRJTbNT26caRZJ";
          var encrypted = "MzVWX4tH4yZWc/w75zUagUMEsP34ywSYISsIIS9fj0W3Q/lR0hBrHmdvMOt106PlKhN/1zXFBPbyKmI6nWC5BN54GuGFSjkxfuansJkfoi0=";
  
          var yeah = OpenSSLDecrypt(encrypted, secret);
          Console.WriteLine(yeah);
          Console.ReadKey();
      }
  
      public static string OpenSSLDecrypt(string encrypted, string passphrase)
      {
          // base 64 decode
          byte[] encryptedBytesWithSalt = Convert.FromBase64String(encrypted);
          // extract salt (first 8 bytes of encrypted)
          byte[] salt = new byte[8];
          byte[] encryptedBytes = new byte[encryptedBytesWithSalt.Length - salt.Length - 8];
          Buffer.BlockCopy(encryptedBytesWithSalt, 8, salt, 0, salt.Length);
          Buffer.BlockCopy(encryptedBytesWithSalt, salt.Length + 8, encryptedBytes, 0, encryptedBytes.Length);
          // get key and iv
          byte[] key, iv;
          DeriveKeyAndIV(passphrase, salt, out key, out iv);
          return DecryptStringFromBytesAes(encryptedBytes, key, iv);
      }
  
      private static void DeriveKeyAndIV(string passphrase, byte[] salt, out byte[] key, out byte[] iv)
      {
          // generate key and iv
          List&lt;byte&gt; concatenatedHashes = new List&lt;byte&gt;(48);
  
          byte[] password = Encoding.UTF8.GetBytes(passphrase);
          byte[] currentHash = new byte[0];
          MD5 md5 = MD5.Create();
          bool enoughBytesForKey = false;
          // See http://www.openssl.org/docs/crypto/EVP_BytesToKey.html#KEY_DERIVATION_ALGORITHM
          while (!enoughBytesForKey)
          {
              int preHashLength = currentHash.Length + password.Length + salt.Length;
              byte[] preHash = new byte[preHashLength];
  
              Buffer.BlockCopy(currentHash, 0, preHash, 0, currentHash.Length);
              Buffer.BlockCopy(password, 0, preHash, currentHash.Length, password.Length);
              Buffer.BlockCopy(salt, 0, preHash, currentHash.Length + password.Length, salt.Length);
  
              currentHash = md5.ComputeHash(preHash);
              concatenatedHashes.AddRange(currentHash);
  
              if (concatenatedHashes.Count &gt;= 48)
                  enoughBytesForKey = true;
          }
  
          key = new byte[32];
          iv = new byte[16];
          concatenatedHashes.CopyTo(0, key, 0, 32);
          concatenatedHashes.CopyTo(32, iv, 0, 16);
  
          md5.Clear();
      }
  
      static string DecryptStringFromBytesAes(byte[] cipherText, byte[] key, byte[] iv)
      {
          // Check arguments.
          if (cipherText == null || cipherText.Length &lt;= 0)
              throw new ArgumentNullException("cipherText");
          if (key == null || key.Length &lt;= 0)
              throw new ArgumentNullException("key");
          if (iv == null || iv.Length &lt;= 0)
              throw new ArgumentNullException("iv");
  
          // Declare the RijndaelManaged object
          // used to decrypt the data.
          RijndaelManaged aesAlg = null;
  
          // Declare the string used to hold
          // the decrypted text.
          string plaintext;
  
          // Create a RijndaelManaged object
          // with the specified key and IV.
          aesAlg = new RijndaelManaged { Mode = CipherMode.CBC, Padding = PaddingMode.None, KeySize = 256, BlockSize = 128, Key = key, IV = iv };
  
          // Create a decrytor to perform the stream transform.
          ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
          // Create the streams used for decryption.
          using (MemoryStream msDecrypt = new MemoryStream(cipherText))
          {
              using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
              {
                  using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                  {
                      // Read the decrypted bytes from the decrypting stream
                      // and place them in a string.
                      plaintext = srDecrypt.ReadToEnd();
                      srDecrypt.Close();
                  }
              }
          }
  
          return plaintext;
      }
  }
  </code></pre>