【发布时间】:2011-07-23 18:25:52
【问题描述】:
我想压缩然后加密我的数据,为了提高速度(通过不必写入字节数组和返回)决定将用于压缩和加密的流链接在一起。
当我写入(压缩和加密)数据时它工作得很好,但是当我尝试读取数据(解压缩和解密)时,读取操作中断 - 只需调用 Read 一次读取正好 0 字节,因为第一次读取总是返回 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();
【问题讨论】:
-
您每次都从字节 0 开始覆盖。您将需要添加一个偏移量变量,该变量从 0 开始并增加每次读取的字节数 - 否则您将继续覆盖缓冲区的开头。
-
感谢您的关注;你就在那里 - 我用以下内容替换了循环:
int offset = 0; while (offset < originalSize) { offset += zip.Read(buffer, offset, originalSize - offset); }不幸的是,这并没有解决问题;我仍然得到剩下的 1 个字节并且它挂起。 (回想起来,如果错误的循环是罪魁祸首,那么解密的数据就不会是完美的)。 -
是的,当我看到它无法解决挂起字节的问题时,我将其作为答案删除,并将其添加为评论。我只是认为它可能会为您节省第二轮令人头疼的问题,想知道为什么缓冲区被破坏了:)
-
这可能很奇怪...你可以尝试添加一个
bytesRead变量,它捕获读取的值,然后只运行逻辑等,如果这是 positive?我想知道它最后是否返回负数(iirc 这将是一个有效的终止符,因为从内存中它只是指出非正数是数据结束,尽管我最近没有检查过这方面的文档) -
试过了,它永远不会返回负数:
标签: c# .net encryption c#-4.0 compression