我想压缩然后加密我的数据,并且为了提高速度(不必写字节数组和返回字节),决定将用于压缩和加密的流链接在一起。
当我写入(压缩和加密)数据时,它可以完美工作,但是当我尝试读取数据(解压缩和解密)时,Read操作会中断-只需调用一次Read即可精确读取0字节,因为第一个Read始终返回0。像下面的代码中那样循环几乎可以工作,除了在特定点上,Read会停止返回大于0的任何值,即使仍然有要读取的数据也是如此。
最后几个字节之前的所有内容均经过完美解压缩和解密。
对于相同的明文,剩下的字节数保持不变。例如,某个字符串始终为9个字节,而另一个字符串始终为1个字节。
以下是相关的加密和解密代码;关于可能出什么问题的任何想法?
加密:
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV))
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
using (DeflateStream zip = new DeflateStream(csEncrypt, CompressionMode.Compress, true))
{
zip.Write(stringBytes, 0, stringBytes.Length);
csEncrypt.FlushFinalBlock();
解密:
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream())
{
// Writes the actual data (sans prepended headers) to the stream
msDecrypt.Write(stringBytes, prependLength, stringBytes.Length - prependLength);
// Reset position to prepare for read
msDecrypt.Position = 0;
// init buffer to read to
byte[] buffer = new byte[originalSize];
using (ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV))
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
using (DeflateStream zip = new DeflateStream(csDecrypt, CompressionMode.Decompress))
{
// Hangs with "offset" at a small, deterministic number away from originalSize (I've gotten 9 less and 1 less for different strings)
// Loop fixed as per advice
int offset = 0;
while (offset < originalSize)
{
int read = zip.Read(buffer, offset, originalSize - offset);
if (read > 0)
offset += read;
else if (read < 0)
Console.WriteLine(read); // Catch it if it happens.
}
// Hangs with "left" at a small, deterministic number (I've gotten 9 and 1 for different strings)
/*
for (int left = buffer.Length; left > 0; )
left -= zip.Read(buffer, 0, left);
*/
解决方案(对加密的修改):
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV))
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (DeflateStream zip = new DeflateStream(csEncrypt, CompressionMode.Compress, true))
zip.Write(stringBytes, 0, stringBytes.Length);
//Flush after DeflateStream is disposed.
csEncrypt.FlushFinalBlock();
最佳答案
问题在于以下几行:
csEncrypt.FlushFinalBlock();
如果您删除了该代码,则该代码将起作用。
原因是,当您写入
DeflateStream
时,并非所有数据都被写入基础流。仅当您通过离开Close()
块显式或隐式调用Dispose()
或using
时,才会发生这种情况。因此,在您的代码中,会发生以下情况:
Write()
编码为DeflateStream
,后者又将大多数数据写入底层的CryptoStream
。 csEncrypt.FlushFinalBlock()
,它将关闭CryptoStream
。 using
的DeflateStream
块,该块尝试将其余数据写入已经关闭的CryptoStream
中。 using
,则保留CryptoStream
的FlushFinalBlock()
块,它将调用Write()
。 正确的事件顺序是:
DeflateStream
编码为CryptoStream
,后者又将大多数数据写入基础using
。 DeflateStream
的CryptoStream
块,该块将其余数据写入已经关闭的using
中。 CryptoStream
的FlushFinalBlock()
块,该块将调用ojit_code。 尽管我希望写入封闭流会因异常而失败。我不确定为什么不会发生这种情况。
关于c# - 读取时链接的GZipStream/DeflateStream和CryptoStream(AES)中断,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6802398/