I am trying to test my cryptography code and keep getting the CyrptographicException "Padding is invalid and cannot be removed" when ever decrypt
is disposed. I get a similar error if I try to read past the end of the decrypt
stream, even though the CryptoStream.Read
documentation indicates that this should not be an issue.
A simplified example:
const int DATA_SET_SIZES = 102399;
byte[] iv,
key,
startingData = new byte[DATA_SET_SIZES],
encryptedData = new byte[((DATA_SET_SIZES - 1) / 16 + 2) * 16],
endingData = new byte[DATA_SET_SIZES];//[((DATA_SET_SIZES - 1) / 16 + 1) * 16];
Random rand = new Random();
rand.NextBytes(startingData); //Get test data.
using (Rijndael cryptAlg = Rijndael.Create())
{
cryptAlg.Mode = CipherMode.CBC;
cryptAlg.Padding = PaddingMode.ISO10126;
iv = cryptAlg.IV; //Use random IV during test.
key = cryptAlg.Key; //Use random Key during test.
using (CryptoStream encrypt = new CryptoStream(new MemoryStream(encryptedData), cryptAlg.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
encrypt.Write(startingData, 0, startingData.Length);
encrypt.FlushFinalBlock();
}
using (CryptoStream decrypt = new CryptoStream(new MemoryStream(encryptedData), cryptAlg.CreateDecryptor(key, iv), CryptoStreamMode.Read))
{
int dataRecieved = decrypt.Read(endingData, 0, endingData.Length);
}
}
If I do one of the following then the exception goes away:
cryptAlg.Padding = PaddingMode.None
after performing the encryption but before creating decrypt
.const int DATA_SET_SIZES = 102400
or any other multiple of the block size.Am I doing something wrong or does the .NET implementation not recognize the end of the stream correctly?
Also, does anyone know why the encrypted data is 1 block longer then would be needed to store the encrypted data? What is in that block?
Your encryptedData
buffer is too large. Take input 15 bytes, then you get 32 blocks of buffer back. Since you give the full buffer to the MemoryStream
constructor, it will read up to the end of the stream. Block decryption will never fail, so the only thing that will fail is the padding. The last block probably only contains zero's, so the decrypted value is random instead of matching the padding format (most of the time).
Try: new byte[(DATA_SET_SIZES / 16 +
1
) * 16]