簡體   English   中英

使用StreamWriter寫入流(用於大流加密)

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

我正在關注Rijndael加密MSDN示例 ,只是我想加密並返回一個流。

以下不起作用。

它沒有拋出任何異常,但在單步執行代碼后,返回值沒有數據。

        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;


        }

我查看了Stream.Writer類文檔 ,認為它與它有關,不支持寫入Stream。

我注意到有一個'對象'類型參數,所以我假設它會工作......這是正確的嗎? 如果沒有,我該怎么辦?

順便說一句,我將FileStream傳遞給它。 逐步執行代碼,plainStream確實包含數據。

以下是一些加密和解密流的示例函數(用您喜歡的算法替換算法):

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);
        }
    }
}

您可以將它們與任何輸出流一起使用。 如果你想寫一個大的輸出流,你可以直接使用那個輸出流(例如FileStream或ASP.NET Response.OutputStream等),你不應該使用一個中間的MemoryStream,它會消耗內存而不是真正的目的。

話雖這么說,如果你真的想使用MemoryStream,你會這樣做:

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

使用流級別復制將一個流的內容復制到另一個流或使用相應的讀/寫器對(如TextReader / TextWriter ) - 如果混合比最有可能得到錯誤的結果。 即流級副本:

 plainStream.CopyTo(csEncrypt);

除了實際將數據寫入加密流(而不是由於StreamWrite.Write(Object)調用而得到的plainStream的類型名稱)之外,您應該使用MemoryStream.ToArray來復制結果內容 - 否則您將獲得“對象處置異常” 。

復制代碼應如下所示,而不是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