2

我正在尝试测试我的加密代码并在处理时不断收到 CyrptographicException“填充无效且无法删除” decrypt。如果我尝试读取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 个块?那个区块里有什么?

4

1 回答 1

2

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

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

于 2013-03-02T16:22:35.230 回答