2

I am writing some C# encrypting that is decrypted by php. They aren't working together very well. The php client has informed me of their configuration (RSSL_KEYGEN_PKCS5_V20, 256 bit AES in CBC mode, RSSL_PAD_ANSIX923). Here is what I put together:

public static byte[] Encrypt(byte[] plainText, string password,
         CipherMode cipherMode, int keySize, PaddingMode paddingMode)
    {
        byte[] salt = new byte[8];
        new RNGCryptoServiceProvider().GetBytes(salt);

        // PKCS#5 V2.0 PBKDF2 keyGenerator (uses default iteration count of 1000) 
        Rfc2898DeriveBytes keyGenerator = new Rfc2898DeriveBytes(password, salt);

        AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
        aes.Mode = cipherMode;
        aes.KeySize = keySize;
        aes.Padding = paddingMode;
        aes.Key = keyGenerator.GetBytes(aes.KeySize / 8);

        // aes.Padding is left default PaddingMode.PKCS7 
        // aes.IV should be automatically set to some random value by .NET 
        // (as described in http://msdn.microsoft.com/en-us/library/5e9ft273(VS.71).aspx) 

        // Overestimate encrypted size requirements 
        byte[] encryptedDataBuffer = new byte[plainText.Length + 32 + 32 + 8];
        MemoryStream encryptedOutput = new MemoryStream(encryptedDataBuffer, true);
        CryptoStream encStream = new CryptoStream(encryptedOutput, aes.CreateEncryptor(),
                                                  CryptoStreamMode.Write);

        encryptedOutput.Write(salt, 0, salt.Length);
        encryptedOutput.Write(aes.IV, 0, aes.IV.Length);
        encStream.Write(plainText, 0, plainText.Length);

        encStream.FlushFinalBlock();
        byte[] encryptedData = new byte[encryptedOutput.Position];
        Array.Copy(encryptedDataBuffer, encryptedData, encryptedData.Length);
        encStream.Close();

        return encryptedData;
    }

I can encrypt and decrypt it on my side, but they cannot decrypt it. Is there something I am doing wrong here? I pass in something like this:

Encrypt(mytext, myPassword, CipherMode.CBC, 256, PaddingMode.ANSIX923);

Thanks.

4
  • 1
    Are you sure that they're using the same number of rounds (1000) in the key generation? Commented Jan 22, 2011 at 23:39
  • Should be. That is the default setting. Commented Jan 23, 2011 at 0:58
  • 2
    c# and PHP tagged in the same question? this can't be true... Commented Jan 23, 2011 at 3:06
  • maybe there should be an 'oil and water' badge for it. Commented Jan 29, 2013 at 19:25

3 Answers 3

2

This was a challenge for myself due to the differing ways that .NET and mcrypt handle 'default' AES256 imlpementations. In some versions of PHP, m_crypt uses zero padding, so you'll have to setup the .NET end to do the same thing:

symmetricKey.Padding = PaddingMode.Zeros;

I posted a sample PHP & C# solution to github to help others who come across the same problem: https://github.com/dchymko/.NET--PHP-encryption

Sign up to request clarification or add additional context in comments.

Comments

1

Narrow it down first: Are you generating the same key?

Once you're certain of that, then you can consider the encyption.

Comments

0

Using the CryptoServiceProvider did the trick.

 Encoding stringEncoding = new System.Text.UTF8Encoding();

        byte[] salt = new byte[8];

        new RNGCryptoServiceProvider().GetBytes(salt);

        AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
        aes.Mode = cipherMode;
        aes.KeySize = keySize;

        aes.Key = stringEncoding.GetBytes(password);
        aes.IV = new byte[aes.IV.Length];

        // Overestimate encrypted size requirements 
        byte[] encryptedDataBuffer = new byte[plainText.Length + 32 + 32 + 8];
        MemoryStream encryptedOutput = new MemoryStream(encryptedDataBuffer, true);

        CryptoStream encStream = new CryptoStream(encryptedOutput, aes.CreateEncryptor(),
                                                  CryptoStreamMode.Write);

        encStream.Write(plainText, 0, plainText.Length);

        encStream.FlushFinalBlock();
        byte[] encryptedData = new byte[encryptedOutput.Position];
        Array.Copy(encryptedDataBuffer, encryptedData, encryptedData.Length);
        encStream.Close();

        return encryptedData;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.