Search code examples
c#encryptioncryptographyaes

c# AES decryption errors with "Padding is invalid and cannot be removed."


I am trying to write client software which performs AES encryption and decryption of messages to a device using c#.

Using the AES class from System.Security.Cryptography, there is no problem sending encrypted messages to the device. The device decrypts these successfully.

The problem occurs when decrypting messages received from the device. We get the message: "Padding is invalid and cannot be removed."

I have searched the web and tried three different approaches but all have the same error - see below. I also tried the three approaches without setting the KeySize property.

In addition to the client being written in C#, a python client was also written where there everything works fine - using the python aes library. So, having got a python version I was able to compare the lengths of the received cipherText which is 32 bytes long and is a byte array. 15 bytes are padding. I really appreciate help.

Option 1
byte[] messageBuffer = null;
using (Aes aesAlg = Aes.Create())
{
    aesAlg.BlockSize = 128;
    aesAlg.KeySize = 128;
    aesAlg.Mode = CipherMode.CBC;
    aesAlg.Key = encryptionKey;  //used by device to encrypt. encryptionKey is a 16 byte array
    aesAlg.IV = sentIV; //This agrees with the IV that was used to encrypt the message by the device. sentIV is a 16 byte array
    //aesAlg.Padding = PaddingMode.PKCS7;  // this makes no difference

    byte[] cipherText = encryptedMessagePart;   //encryptedMessagePart is byte[] encryptedMessagePart

    // Create a decrytor to perform the stream transform. 
    ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

    try
    {
        messageBuffer = decryptor.TransformFinalBlock(cipherText, 0, cipherText.Length);  //****fails here ********************
    }

    catch (Exception ex)
    {
        ....;
    }
}



Option 2
byte[] messageBuffer = new byte [1024];
using (Aes aesAlg = Aes.Create())
{
    aesAlg.BlockSize = 128;
    aesAlg.KeySize = 128;
    aesAlg.Mode = CipherMode.CBC;
    aesAlg.Key = encryptionKey;  //used by device to encrypt. encryptionKey is a 16 byte array
    aesAlg.IV = sentIV; //This agrees with the IV that was used to encrypt the message by the device. sentIV is a 16 byte array
    //aesAlg.Padding = PaddingMode.PKCS7;  // this makes no difference

    byte[] cipherText = encryptedMessagePart; //encryptedMessagePart is byte[] encryptedMessagePart

    // Create a decrytor to perform the stream transform. 
    ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
    using (var msDecrypt = new MemoryStream(cipherText))
    {
        using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
        {
            try
            {
                var zx = csDecrypt.Read(messageBuffer, 0, cipherText.Length); //****fails here ********************
            }
            catch (Exception ex)
            {
                ....;
            }
       }
    }
}


Option 3
byte[] messageBuffer = new byte [1024];
using (Aes aesAlg = Aes.Create())
{
    aesAlg.BlockSize = 128;
    aesAlg.KeySize = 128;
    aesAlg.Mode = CipherMode.CBC;
    aesAlg.Key = encryptionKey;  //used by device to encrypt. encryptionKey is a 16 byte array
    aesAlg.IV = sentIV; //This agrees with the IV that was used to encrypt the message by the device. sentIV is a 16 byte array
    //aesAlg.Padding = PaddingMode.PKCS7;  // this makes no difference

    byte[] cipherText = encryptedMessagePart; //encryptedMessagePart is byte[] encryptedMessagePart

    // Create a decrytor to perform the stream transform. 
    ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
    using (var msDecrypt = new MemoryStream(cipherText))
    {
        using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
        {
        using (var srDecrypt = new StreamReader(csDecrypt))
            {
                try
                {
                    // Read the decrypted bytes from the decrypting stream 
                    // and place them in a string. 
                    var pt = srDecrypt.ReadToEnd(); //****fails here ********************
                    messageBuffer = Utils.GetBytes(pt); //convert to bytes
                }
                catch (Exception ex)
                {
                    ....;
                }
            }
        }
    }
}

Solution

  • Padding errors are expected for anything where the key or message has been corrupted. For small messages smaller than one block it could also be that the IV is incorrectly handled. As the device seems to be using C# that's the most likely cause.

    Much less likely, but possible, is that ISO 10126 padding is used. PKCS#7 padded messages can be unpadded using an ISO 10126 unpadding routine. However, the reverse is not true as PKCS#7 relies on all the values in the padding to be correct, not just the last one. In ISO 10126 padding only the last byte indicates the amount of padding bytes used; the other bytes may have any value.

    You can of course always have a look yourself. Simply indicate "no padding" and print out the message in hexadecimals. If the message is total garbage either the message or even more likely the key is incorrect. If it looks OK then you should be able to distinguish the padding method from the last bytes; the Wikipedia article on padding lists all the common schemes.