看来
THIS question is related,
但事实并非如此。
在我的例子中,当
正在解密
,在相关问题中,它是何时
加密
人们问的第一个问题是:你试过什么?我试过很多次了。所以,即使删除了所有多余的文本,我的描述也相当长。对不起。
我的结论是,在
CryptoSteam.FlushFinalBlock
,由调用
CryptoStream.Dispose()
. 如果没有从流中读取任何内容,则会发生这种情况。
Reference source CryptoStream.FlushFinalBlock
如果我在解密过程中读取所有数据或至少一个字节,一切都会正常工作。
如果我什么也没读,我会得到一个密码例外。
填充无效,无法删除。
-
以下是完整的加密/解密周期。工作正常,没有异常,不需要更改默认填充,不需要FlushFinalBlock。读取的数据等于原始数据
-
如果我只读取一个字节:也没有异常,不需要更改默认填充,不需要FlushFinalBlock。正确的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())
{
rijndael.GenerateKey();
rijndael.GenerateIV();
key = rijndael.Key;
iv = rijndael.IV;
using (var encryptor = rijndael.CreateEncryptor())
{
using (var cryptoStream = new CryptoStream(testStream, encryptor,
CryptoStreamMode.Read))
{
using (BinaryReader reader = new BinaryReader(cryptoStream))
{
encryptedData = reader.ReadBytes(10000);
}
}
}
}
}
所有测试字节都加密在EncryptedData中。键和四是已知的
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);
}
}
}
}
}
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))
{
}
}
在开头提到的相关问题中的一个答案包括一个侥幸的结局。这没有如预期的那样有帮助,因为CrypteStream.Dispose已经调用了此
using (Stream decryptedStream = new CryptoStream(encryptedStream, decryptor,
CryptoStreamMode.Read))
{
using (BinaryReader reader = new BinaryReader(decryptedStream))
{
if (!decryptedStream.HasFlushedFinalBlock)
{
decryptedStream.FlushFinalBlock();
}
}
}
所以现在我们知道异常的发生是因为
CryptoStream.FlushFinalBlock
,也可以在
CryptoStream.Dispose()。
这个问题与二进制阅读器无关。如果我直接读取一个字节,那么就没有异常,如果不读取任何内容,我将在释放密码流期间获取异常。
using (Stream decryptedStream = new CryptoStream(encryptedStream, decryptor,
CryptoStreamMode.Read))
{
int b = decryptedStream.ReadByte();
}
那么,我应该怎么做来防止这个异常呢?读取一个虚拟字节?看起来有点傻,不是吗?