简体   繁体   English

使用StreamWriter写入流(用于大流加密)

[英]Using StreamWriter to write in a Stream (for large Stream encryption)

I am following the MSDN Example of Rijndael Encryption , only that I would like to encrypt and return a stream. 我正在关注Rijndael加密MSDN示例 ,只是我想加密并返回一个流。

The following does not work. 以下不起作用。

It throws no exception but after stepping through the code, the return value has no data. 它没有抛出任何异常,但在单步执行代码后,返回值没有数据。

        public static Stream EncryptStream(Stream plainStream, byte[] Key, byte[] IV)
        {

            var encrypted = new MemoryStream()

            // Create an RijndaelManaged object 
            // with the specified key and IV. 
            using (RijndaelManaged rijAlg = new RijndaelManaged())
            {
                rijAlg.Key = Key;
                rijAlg.IV = IV;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);

                // Create the streams used for encryption. 
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {

                            //Write all data to the stream.
                            swEncrypt.Write(plainStream);
                        }
                        msEncrypt.CopyTo(encrypted);
                    }
                }
            }
            return encrypted;


        }

I looked at the documentation for the Stream.Writer class , thinking that it has something to do with it not supporting writing to a Stream. 我查看了Stream.Writer类文档 ,认为它与它有关,不支持写入Stream。

I noticed that there is an 'object' type parameter, so I am assuming it would work... Is that correct? 我注意到有一个'对象'类型参数,所以我假设它会工作......这是正确的吗? If not, how do I do it? 如果没有,我该怎么办?

I pass a FileStream to it, by the way. 顺便说一句,我将FileStream传递给它。 Stepping through the code, plainStream does contain data. 逐步执行代码,plainStream确实包含数据。

Here are some sample function to encrypt and decrypt from and to streams (replace the algo by the one you prefer): 以下是一些加密和解密流的示例函数(用您喜欢的算法替换算法):

public static void Decrypt(Stream input, Stream output, byte[] key, byte[] iv)
{
    using (SymmetricAlgorithm algo = SymmetricAlgorithm.Create()) // Creates the default implementation, which is RijndaelManaged. 
    {
        using (CryptoStream stream = new CryptoStream(input, algo.CreateDecryptor(key, iv), CryptoStreamMode.Read))
        {
            byte[] bytes = new byte[16];
            int read;
            do
            {
                read = stream.Read(bytes, 0, bytes.Length);
                output.Write(bytes, 0, read);
            }
            while (read > 0);
        }
    }
}

public static void Encrypt(Stream input, Stream output, byte[] key, byte[] iv)
{
    using (SymmetricAlgorithm algo = SymmetricAlgorithm.Create()) //Creates the default implementation, which is RijndaelManaged. 
    {
        using (CryptoStream stream = new CryptoStream(output, algo.CreateEncryptor(key, iv), CryptoStreamMode.Write))
        {
            byte[] bytes = new byte[16];
            int read;
            do
            {
                read = input.Read(bytes, 0, bytes.Length);
                stream.Write(bytes, 0, read);
            }
            while (read > 0);
        }
    }
}

You can use them with any output stream. 您可以将它们与任何输出流一起使用。 If you want to write to a large output stream, you can use that output stream directly (for example a FileStream or ASP.NET Response.OutputStream, etc.), you should not use an intermediary MemoryStream which will consume memory for no real purpose. 如果你想写一个大的输出流,你可以直接使用那个输出流(例如FileStream或ASP.NET Response.OutputStream等),你不应该使用一个中间的MemoryStream,它会消耗内存而不是真正的目的。

That being said, if you really want to use a MemoryStream, you would do it like this: 话虽这么说,如果你真的想使用MemoryStream,你会这样做:

MemoryStream output = new MemoryStream();
Encrypt(input, output, key, iv);
output.Position = 0; // rewind the stream, so you can use it from the beginning

Use stream level copy to copy content of one stream to another OR use corresponding pair of Reader/Writer (like TextReader / TextWriter ) - if you mix than most likely you get wrong result. 使用流级别复制将一个流的内容复制到另一个流或使用相应的读/写器对(如TextReader / TextWriter ) - 如果混合比最有可能得到错误的结果。 Ie stream level copy: 即流级副本:

 plainStream.CopyTo(csEncrypt);

In addition to actually writing data to the encrypted stream (instead of type name of plainStream which you get due to StreamWrite.Write(Object) call) you should use MemoryStream.ToArray to copy resulting content - otherwise you are getting "object disposed exception". 除了实际将数据写入加密流(而不是由于StreamWrite.Write(Object)调用而得到的plainStream的类型名称)之外,您应该使用MemoryStream.ToArray来复制结果内容 - 否则您将获得“对象处置异常” 。

Copy code should look like following instead of msEncrypt.CopyTo(encrypted); 复制代码应如下所示,而不是msEncrypt.CopyTo(encrypted);

var bytes = msEncrypt.ToArray();
encrypted.Write(bytes, 0, bytes.Length);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM