2013-11-01 17 views
18

我創建了一個MemoryStream,將它傳遞給CryptoStream進行編寫。我想CryptoStream加密,並保留我打開MemoryStream然後讀入其他東西。但一旦CryptoStream配置,它也配置MemoryStreamCryptoStream是否可以讓基礎流開放?

可以CryptoStream離開基地MemoryStream打開莫名其妙?

using (MemoryStream scratch = new MemoryStream()) 
{ 
    using (AesManaged aes = new AesManaged()) 
    { 
     // <snip> 
     // Set some aes parameters, including Key, IV, etc. 
     // </snip> 
     ICryptoTransform encryptor = aes.CreateEncryptor(); 
     using (CryptoStream myCryptoStream = new CryptoStream(scratch, encryptor, CryptoStreamMode.Write)) 
     { 
      myCryptoStream.Write(someByteArray, 0, someByteArray.Length); 
     } 
    } 
    // Here, I'm still within the MemoryStream block, so I expect 
    // MemoryStream to still be usable. 
    scratch.Position = 0; // Throws ObjectDisposedException 
    byte[] scratchBytes = new byte[scratch.Length]; 
    scratch.Read(scratchBytes,0,scratchBytes.Length); 
    return Convert.ToBase64String(scratchBytes); 
} 
+0

爲什麼你首先使用流?只需在輸入字節上調用'encryptor.TransformFinalBlock'即可。數據流主要用於增量加密/解密,但不能在同時提供完整數據時使用。 – CodesInChaos

回答

9

你可以但你不能使用使用語句。您需要手動管理對象的處理,並且您還需要調用FlushFinialBlock()以確保在處理之前將所有數據寫入基礎流。

一旦你完成了對流的所有工作,你就可以將最後在finally塊中等待的所有資源都處理掉。

MemoryStream scratch = null; 
AesManaged aes = null; 
CryptoStream myCryptoStream = null; 
try 
{ 
    scratch = new MemoryStream(); 
    aes = new AesManaged(); 

    // <snip> 
    // Set some aes parameters, including Key, IV, etc. 
    // </snip> 
    ICryptoTransform encryptor = aes.CreateEncryptor(); 
    myCryptoStream = new CryptoStream(scratch, encryptor, CryptoStreamMode.Write); 
    myCryptoStream.Write(someByteArray, 0, someByteArray.Length); 

    //Flush the data out so it is fully written to the underlying stream. 
    myCryptoStream.FlushFinalBlock(); 

    scratch.Position = 0; 
    byte[] scratchBytes = new byte[scratch.Length]; 
    scratch.Read(scratchBytes,0,scratchBytes.Length); 
    return Convert.ToBase64String(scratchBytes); 
} 
finally 
{ 
    //Dispose all of the disposeable objects we created in reverse order. 

    if(myCryptoStream != null) 
     myCryptoStream.Dispose(); 

    if(aes != null) 
     aes.Dispose(); 

    if(scratch != null) 
     scratch.Dispose(); 
} 
+1

對於給我一個-1的人,我認爲我的答案是「沒有用」來保證-1?如果我的帖子中有不正確的信息,請通知我,以便我可以更正或刪除它。我猜測代碼被寫入內部'try-finally'的方式是不必要的。我將刪除它。我唯一能想到的其他事情是'aes'和'scratch'在myCryptoStream之前被處理。我也會糾正這一點。 –

+1

如果你想編寫一個方法,它在加密後返回基本流,並在返回基本流之前處理CryptoStream?如果你處理CryptoStream,這有什麼關係嗎?或者當你完成它的時候處置BaseStream就可以了嗎? –

+0

Downvoted:沒有解決如何從使用CryptoStream的方法返回基礎流 – Hammerite

6

事實證明,沒有任何需要掰開使用{}塊到嘗試{}終於{} ...最後,你只需要使用FlushFinalBlock()using語句裏面,並根據需要在其中嵌入其他任何東西。

using (MemoryStream scratch = new MemoryStream()) 
{ 
    using (AesManaged aes = new AesManaged()) 
    { 
     // <snip> 
     // Set some aes parameters, including Key, IV, etc. 
     // </snip> 
     ICryptoTransform encryptor = aes.CreateEncryptor(); 
     using (CryptoStream myCryptoStream = new CryptoStream(scratch, encryptor, CryptoStreamMode.Write)) 
     { 
      myCryptoStream.Write(someByteArray, 0, someByteArray.Length); 
      myCryptoStream.FlushFinalBlock(); 
      scratch.Flush(); // not sure if this is necessary 
      byte[] scratchBytes = scratch.ToArray(); 
      return Convert.ToBase64String(scratchBytes); 
     } 
    } 
} 
+2

'scrach.Flush()'確實是不明智的,[來自msdn](http://msdn.microsoft.com/ 「*覆蓋Stream.Flush方法,以便不採取任何行動*」 –

11

作爲第二個解決方案,您可以簡單地通過沿除物/關閉每個調用WrapperStream對象。圍繞你的內存流做一個包裝,把包裝器交給加密流,現在關閉加密流不會觸及內存流。

5

我簡單的解決方案:

class NotClosingCryptoStream : CryptoStream 
{ 
    public NotClosingCryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode) 
     : base(stream, transform, mode) 
    { 
    } 

    protected override void Dispose(bool disposing) 
    { 
     if(!HasFlushedFinalBlock) 
      FlushFinalBlock(); 

     base.Dispose(false); 
    } 
}
+0

它的工作原理,但我有一個問題:正如MSDN提到的 '處置 類型:系統。布爾型 爲true,釋放託管資源和非託管資源;假只釋放非託管資源。 但據我所知,Stream對象是非託管對象,所以這個解決方案如何防止CryptoStream不發佈基礎流? – Gintama

0

由於@Cyber​​Basti回答。我認爲最好的解決方案是重寫處置方法並調用基地false

我看着reference source,它顯示是最好的解決辦法,因爲你仍然可以使用using關鍵字並進行有組織的代碼:)

順便說一句我正在做的答案,因爲我不能發表評論xD

相關問題