部分读取最终块后的填充错误

时间:2013-03-02 05:53:40

标签: c# cryptography rijndael

我正在尝试测试我的加密代码,并在处理decrypt时不断收到CyrptographicException“Padding无效且无法移除”。如果我尝试阅读decrypt流的末尾,即使CryptoStream.Read文档表明这不应该是一个问题,我也会收到类似的错误。

简化示例:

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);
    }
}

如果我执行以下操作之一,那么例外就会消失:

  • 执行加密后但在创建cryptAlg.Padding = PaddingMode.None之前更改decrypt
  • 更改const int DATA_SET_SIZES = 102400或块大小的任何其他倍数。
  • 不要读取最后一个块中的任何数据。

我做错了什么或.NET实现无法正确识别流的结尾?

此外,有谁知道为什么加密数据比存储加密数据需要长1个块?那个街区里有什么?

1 个答案:

答案 0 :(得分:2)

您的encryptedData缓冲区太大了。输入15个字节,然后返回32块缓冲区。由于您将完整缓冲区提供给MemoryStream构造函数,因此它将读取到流的末尾。块解密将从不失败,因此唯一失败的是填充。最后一个块可能只包含零,因此解密后的值是随机的,而不是匹配填充格式(大部分时间)。

尝试:new byte[(DATA_SET_SIZES / 16 + 1 ) * 16]