Pergunta

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:

  • Change cryptAlg.Padding = PaddingMode.None after performing the encryption but before creating decrypt.
  • Change const int DATA_SET_SIZES = 102400 or any other multiple of the block size.
  • Do not read any data from the last block.

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?

Foi útil?

Solução

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]

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top