DECRYPTING时:填充无效,如果没有读取则无法删除

时间:2018-06-07 10:05:12

标签: c# encryption stream

似乎是THIS question is related,,但事实并非如此 在我的情况下,解密时会出现“填充无效且无法删除”的异常,相关问题是加密

人们问的第一个问题是:你尝试过什么?我已经尝试了很多。因此,即使删除了所有多余的文本,我的描述也很长。对不起。

  

我的结论是CryptoSteam.FlushFinalBlock内的CryptoStream.Dispose()抛出了“填充无效且无法删除”的异常。如果没有从Stream中读取任何内容,就会发生这种情况。

Reference source CryptoStream.FlushFinalBlock

如果我在解密过程中读取所有数据或至少一个字节,一切正常。

如果我什么都没读,我会得到一个CryptoGraphicException。 填充无效,无法删除。

我尝试了以下内容:

  • 完整的加密/解密周期。工作正常,没有异常,无需更改默认填充,不需要FlushFinalBlock。读取数据等于原始数据
  • 如果我只读取一个字节:也没有例外,不需要更改默认填充,不需要FlushFinalBlock。一个适当的Dispose()负责这个
  • 如果我没有阅读任何内容,我会得到提到的例外
  • Dispose之前额外的FlushFinalBlock没有帮助

下面的代码显示了一个完整正常工作的加密/解密测试程序。解密的字节等于原始字节:

数据:

byte[] key;
byte[] iv;
byte[] testData = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
byte[] encryptedData;
byte[] decryptedData;

加密数据:

using (Stream testStream = new MemoryStream(testData))
{
    using (RijndaelManaged rijndael = new RijndaelManaged())
    {   // Generate and remember keys:
        rijndael.GenerateKey();
        rijndael.GenerateIV();
        key = rijndael.Key;
        iv = rijndael.IV;

        using (var encryptor = rijndael.CreateEncryptor())
        {
            using (var cryptoStream = new CryptoStream(testStream, encryptor,
                   CryptoStreamMode.Read))
            {   // read all bytes from the cryptoStream and put in a EncryptedData
                using (BinaryReader reader = new BinaryReader(cryptoStream))
                {
                    encryptedData = reader.ReadBytes(10000);
                    // expect no bytes anymore
                }
            }
        }
    }
}

所有TestBytes都在encryptedData中加密。 key和iv是已知的

解密数据

using (Stream encryptedStream = new MemoryStream(encryptedData))
{
    using (var rijnDael = new RijndaelManaged())
    {
        rijnDael.Key = key;
        rijnDael.IV = iv;
        using (var decryptor = rijnDael.CreateDecryptor())
        {
            using (Stream decryptedStream = new CryptoStream(encryptedStream, decryptor,
                   CryptoStreamMode.Read))
            {
                using (BinaryReader reader = new BinaryReader(decryptedStream))
                {
                    decryptedData = reader.ReadBytes(1000);
                    // expect no bytes anymore
                }
            }
        }
    }
}

// Check that the decrypted data equals the original data:
Debug.Assert(testData.SequenceEqual(decryptedData));

这很好用。如果我只读取一个解密字节,则没有例外:

using (BinaryReader reader = new BinaryReader(decryptedStream))
{
    byte b = reader.ReadByte();
}

但是,如果我什么都没读,则会发生异常:

using (Stream decryptedStream = new CryptoStream(encryptedStream, decryptor,
       CryptoStreamMode.Read))
{
    using (BinaryReader reader = new BinaryReader(decryptedStream))
    {
    } // exception during Dispose()
}

开头提到的相关问题中的一个答案包括FlushFinalBlock。正如预期的那样,这没有用,因为CrypteStream.Dispose已经调用了这个

using (Stream decryptedStream = new CryptoStream(encryptedStream, decryptor,
       CryptoStreamMode.Read))
{
    using (BinaryReader reader = new BinaryReader(decryptedStream))
    {
        if (!decryptedStream.HasFlushedFinalBlock)
        { 
            decryptedStream.FlushFinalBlock();
            // even though it hasn't flushed the final bloc
            // I get the same Exception during Flush
         }
    } 
}

现在我们知道由于CryptoStream.FlushFinalBlock而发生异常,这也是在CryptoStream.Dispose()

中完成的

问题与二进制阅读器无关。如果我直接读取一个字节,那么没有异常,没有读取任何内容我在CryptoStream的Dispose期间得到异常

using (Stream decryptedStream = new CryptoStream(encryptedStream, decryptor,
       CryptoStreamMode.Read))
{
    int b = decryptedStream.ReadByte();
} // exception during Dispose()

那么我应该怎么做以防止异常?读一个虚拟字节?看起来有点傻,不是吗?

0 个答案:

没有答案