簡體   English   中英

Base64-使用StreamWriter的CryptoStream與Convert.ToBase64String()

[英]Base64 - CryptoStream with StreamWriter vs Convert.ToBase64String()

根據Alexei的反饋,問題得到了簡化:

如何使用緩沖的Stream方法將CryptoStream的內容(使用ToBase64Transform)轉換為StreamWriter(Unicode編碼)而不使用Convert.ToBase64String()?

注意:調用Convert.ToBase64String()會引發OutOfMemoryException,因此需要使用緩沖/流方法進行轉換。

您可能應該實現自定義Stream ,而不是TextWriter 編寫流比編寫器容易得多(例如將流傳遞到壓縮流)。

要創建自定義流,請從Stream派生並至少實現WriteFlush (如果需要R / W流,則可以執行Read )。 其余部分或多或少是可選的,取決於您的其他需求,定期復制到其他流不需要其他任何內容。

  • 在構造函數中,將內部流傳遞給您以進行寫入。 Base64始終會產生ASCII字符,因此將帶有或不帶有BOM的UTF-8輸出直接寫到流中應該很容易,但是如果要指定編碼,則可以在內部用StreamWriter包裝內部流。

  • 在您的Write實現緩沖區數據中,直到獲得足夠的字節以具有3字節的倍數的塊(即300),然后在該部分上調用Convert.ToBase64String 確保不要松動尚未轉換的部分。 由於Base64將3字節轉換為4個字符,因此以3的倍數大小的塊進行轉換將永遠不會在末尾添加= / ==填充,並且可以與下一個塊連接。 因此,將轉換后的部分寫入內部流/寫入器。 請注意,您希望將塊大小限制為相對較小的大小,例如3*10000以避免在大對象堆上分配塊。

  • Flush確保轉換最后一個未寫入的字節(這將是最后一個帶有= padding的字節),並將其也寫入流中。

  • 為了進行讀取,您可能需要格外小心,因為在Base64中允許使用空格,因此您無法讀取固定數量的字符並轉換為字節。 最簡單的方法是從StreamReader按字符讀取並將每4個非空格的字符轉換為字節。

注意:您可以考慮直接從字節手動寫入/讀取Base64。 它會給您帶來一些性能上的好處,但是如果您不擅長移位,可能會很難。

請嘗試使用以下內容進行加密。 我正在使用fileName / filePath作為輸入。 您可以根據需要進行調整。 使用此程序,我已成功加密了超過1 GB的文件,沒有任何內存不足異常。

public bool EncryptUsingStream(string inputFileName, string outputFileName)
        {
            bool success = false;

            // here assuming that you already have key
            byte[] key = new byte[128];

            SymmetricAlgorithm algorithm = SymmetricAlgorithm.Create();
            algorithm.Key = key;

            using (ICryptoTransform transform = algorithm.CreateEncryptor())
            {
                CryptoStream cs = null;
                FileStream fsEncrypted = null;
                try
                {
                    using (FileStream fsInput = new FileStream(inputFileName, FileMode.Open, FileAccess.Read))
                    {
                        //First write IV 
                        fsEncrypted = new FileStream(outputFileName, FileMode.Create, FileAccess.Write);
                        fsEncrypted.Write(algorithm.IV, 0, algorithm.IV.Length);

                        //then write using stream
                        cs = new CryptoStream(fsEncrypted, transform, CryptoStreamMode.Write);
                        int bytesRead;
                        int _bufferSize = 1048576; //buggersize = 1mb; 
                        byte[] buffer = new byte[_bufferSize];
                        do
                        {
                            bytesRead = fsInput.Read(buffer, 0, _bufferSize);
                            cs.Write(buffer, 0, bytesRead);
                        } while (bytesRead > 0);

                        success = true;

                    }
                }
                catch (Exception ex)
                {
                    //handle exception or throw.
                }
                finally
                {
                    if (cs != null)
                    {                       
                        cs.Close();
                        ((IDisposable)cs).Dispose();                    

                        if (fsEncrypted != null)
                        {
                            fsEncrypted.Close();
                        }
                    }

                }
            }
            return success;
        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM