Encryption in .NET and decryption in Android throws BadPaddingException: pad block corrupted

StackOverflow https://stackoverflow.com/questions/10424334

Question

I did lot of research but i couldn't find answer to my issue. I'm doing AES encryption (Rijndael block size 128 bits) in .NET and decryption in Android (AES) with same password, salt & IV between them.

C# Encryption code snippet:

        byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
        byte[] saltValueBytes  = Encoding.ASCII.GetBytes(saltValue);

        byte[] plainTextBytes  = Encoding.UTF8.GetBytes(plainText);

        PasswordDeriveBytes password = new PasswordDeriveBytes(
                                                        passPhrase, 
                                                        saltValueBytes, 
                                                        hashAlgorithm, 
                                                        passwordIterations);

        byte[] keyBytes = password.GetBytes(keySize / 8);

        RijndaelManaged symmetricKey = new RijndaelManaged();

        symmetricKey.Padding = PaddingMode.PKCS7;

        symmetricKey.BlockSize = 128;  

        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 cipherText = Convert.ToBase64String(cipherTextBytes);

Android Decryption code snippet:

    KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), iterationCount); 

    SecretKey key = SecretKeyFactory.getInstance( 
            "PBEWithSHA1And128BitAES-CBC-BC").generateSecret(keySpec);

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");

    cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv.getBytes()));

    byte[] decrypted = cipher.doFinal(encrypted);

cipher.doFinal call throws following exception.

"05-02 18:17:38.239: W/System.err(25547): javax.crypto.BadPaddingException: pad block corrupted"

I did set the padding to "PKCS7Padding" in both .NET and Android and the encryption block size to 128 bits.

However, encrypt in Android & decrypt in Android works fine. Same with Encrypt in .NET and Decrypt in .NET works fine too.

Sample Test:

String PlainText            = "hello world";
String EncryptedDotNetblob  = "JyijoGEALMI25Zej7d+fMg==";
String EncryptedAndroidblob = "1HhuTQaLRJEK4zxI9FAO6A==";

as you can see above blobs are different too.

Anyone knows what's the problem here?

Était-ce utile?

La solution

The keys you are deriving are different, that is why you are getting an error (log them as hex strings to check). PasswordDeriveBytes uses a modified version of PBKDF1, on the other hand, SecretKeyFactory.getInstance("PBEWithSHA1And128BitAES-CBC-BC") gives you a key factory that derives keys as specified by PKCS#12. Those are different algorithms, and produce different keys. Use Rfc2898DeriveBytes in .NET and SecretKeyFactory .getInstance("PBKDF2WithHmacSHA1") with the same parameters to get the same key.

Autres conseils

Here is a C# example, you need the IterationCount

protected void Page_Load(object sender, EventArgs e)
{
    string value = "";
    string password = "";
    string salt = "";
    string iv = "";


    byte[] vectorBytes = Convert.FromBase64String(Server.UrlDecode(iv)); 
    byte[] cipherText = Convert.FromBase64String(Server.UrlDecode(value));

    Rfc2898DeriveBytes key1 = new Rfc2898DeriveBytes(password, StringToByteArray(salt)); //same as PBKDF2WithHmacSHA1
    key1.IterationCount = 32;
    byte[] keyBytes = key1.GetBytes(16);

    string Answer = DecryptDataAES(cipherText, keyBytes, vectorBytes); //vectorBytes is good

    //litAnswer.Text = Answer;
}

public static string DecryptDataAES(byte[] cipherText, byte[] key, byte[] iv)
{
    string plaintext = null;

    using (Rijndael rijndael = Rijndael.Create())
    {
        rijndael.Key = key;
        rijndael.IV = iv;
        rijndael.Padding = PaddingMode.None;

        ICryptoTransform decryptor = rijndael.CreateDecryptor(rijndael.Key, rijndael.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))
                {
                    plaintext = srDecrypt.ReadToEnd();
                }
            }
        }
    }
    return plaintext;
}

public static byte[] StringToByteArray(String hex)
{
    int NumberChars = hex.Length / 2;
    byte[] bytes = new byte[NumberChars];
    using (var sr = new StringReader(hex))
    {
        for (int i = 0; i < NumberChars; i++)
            bytes[i] =
              Convert.ToByte(new string(new char[2] { (char)sr.Read(), (char)sr.Read() }), 16);
    }
    return bytes;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top