似乎是THIS question is related,,但事实并非如此 在我的情况下,解密时会出现“填充无效且无法删除”的异常,相关问题是加密
时人们问的第一个问题是:你尝试过什么?我已经尝试了很多。因此,即使删除了所有多余的文本,我的描述也很长。对不起。
我的结论是
CryptoSteam.FlushFinalBlock
内的CryptoStream.Dispose()
抛出了“填充无效且无法删除”的异常。如果没有从Stream中读取任何内容,就会发生这种情况。
Reference source CryptoStream.FlushFinalBlock
如果我在解密过程中读取所有数据或至少一个字节,一切正常。
如果我什么都没读,我会得到一个CryptoGraphicException。 填充无效,无法删除。
我尝试了以下内容:
下面的代码显示了一个完整正常工作的加密/解密测试程序。解密的字节等于原始字节:
数据:
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()
那么我应该怎么做以防止异常?读一个虚拟字节?看起来有点傻,不是吗?