4

这是我的一段代码,它应该加密文件并将密码写入新文件。代码类似于 Microsoft MSDN 网页上的示例。

byte[] inputBuffer = new byte[InputFileStream.Length];
byte[] outputBuffer = new byte[InputFileStream.Length];

InputFileStream.Read(inputBuffer, 0, (int)InputFileStream.Length);

ICryptoTransform encryptor = AesInstance.CreateEncryptor(AesInstance.Key, AesInstance.IV);


            using (MemoryStream memoryStream = new MemoryStream())
            {

                using (CryptoStream stream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter encrypted = new StreamWriter(stream))
                    {

                        encrypted.Write(inputBuffer);

                    }

                    outputBuffer = memoryStream.ToArray();

                    OutputFileStream.Write(outputBuffer, 0, (int)outputBuffer.Length);


                }

            }

OutputFileStream.Close();
InputFileStream.Close();`

问题是输入缓冲区从文件中正确读取字节,但输出缓冲区似乎只有 16 个字节的数据。结果是输出文件只有 16 个字节,即使输入文件很大。错误在哪里?各种模式,ECB,CBC等都存在问题。

4

4 回答 4

2

这个问题很老了,但值得更好的解释。问题隐藏在StreamWriter自身之中。此类应用于将文本写入流。然而,这inputBuffer不是文本。它是一个字节数组!

encrypted.Write(inputBuffer);

等于

encrypted.Write(inputBuffer.ToString());

根据 MSDN StreamWriter.Write(object)

通过调用该对象的 ToString 方法,将对象的文本表示形式写入文本字符串或流。

正确的解决方案是将输入缓冲区直接写入CryptoStream

using (MemoryStream msEncrypt = new MemoryStream(outputBuffer))
{
    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
    {
         csEncrypt.Write(inputBuffer, 0, inputBuffer.Length);
    }
    return msEncrypt.ToArray();
} 
于 2016-09-08T08:34:33.090 回答
0

Ok, it is fixed now. Thanks to Marc response, i figured it out how should it work. Here is working code, if anyone would need it later:

            InputFileStream.Read(inputBuffer, 0, (int)InputFileStream.Length);
            InputFileStream.Flush();
            InputFileStream.Close();

            using (MemoryStream msEncrypt = new MemoryStream(outputBuffer))
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        swEncrypt.Write(inputBuffer);
                        swEncrypt.Flush();
                        swEncrypt.Close();
                    }
                    csEncrypt.Flush();
                    csEncrypt.Close();
                }
                OutputFileStream.Write(outputBuffer, 0, (int)outputBuffer.Length);
                OutputFileStream.Flush();
                OutputFileStream.Close();
            }

Maybe it isn't perfect code (i know it may be redundant) but it works fine even for huge files.

于 2013-05-10T19:18:50.983 回答
0

我相信当你使用

encrypted.Write(inputBuffer);

你没有给作者写缓冲区的大小。

于 2013-05-08T17:46:32.383 回答
0

许多流都进行缓冲,尤其是加密和压缩流。在您关闭/处置加密流之前,不要在 MemoryStream 上调用 ToArray。

            using (CryptoStream stream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
            {
                using (StreamWriter encrypted = new StreamWriter(stream))
                {
                    encrypted.Write(inputBuffer);
                }
            }
            OutputFileStream.Write(memoryStream.GetBuffer(),
                0, (int)memoryStream.Length);
        }

更清楚地说,完全失去 MemoryStream 并在 OutputFileStream 之上创建加密流 - 即使处理大量数据,这也能很好地工作。

于 2013-05-08T17:47:43.667 回答