2013-05-08 98 views
2

這是我的一段代碼,它應該加密文件並將密碼寫入新文件。代碼與Microsoft MSDN網頁上的示例類似。AES C#文件加密 - 流寫入只有16個字節

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等

+0

不要擔心,這是確保在程序邏輯。 – 2013-05-08 19:46:38

回答

0

我相信當你使用

encrypted.Write(inputBuffer); 

你是不是給作家緩衝區的大小來寫。

+0

inputBuffer是一個byte []類型,所以我認爲沒有必要給緩衝區的大小,是嗎? – 2013-05-08 18:19:59

+1

主要問題是'StreamWriter'是'TextStream'的子類,你不能寫一個byte []'緩衝區給它。使用'MemoryStream'代替'WriteStream',並且指定'Write'函數的緩衝區大小,你應該很好去! – 2013-05-08 18:44:06

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頂部的加密數據流 - 這甚至會用大量的數據很好地工作。

+0

感謝您的回覆。可悲的是,我有一個未處理的異常「無法訪問關閉的流」與memoryStream.Lenght一致。 另外,當我丟棄了memoryStream並且只使用了CryptoStream時,我仍然只輸出了16bytes的輸出 – 2013-05-08 18:26:25

+0

@Anna hmm .... crypto-stream構造函數是否擁有擁有/不擁有內部流的選項? – 2013-05-08 18:42:15

+0

AFAIK cryptoStream構造函數僅獲取一個流作爲參數「要執行密碼轉換的流」。 我認爲可能存在沖洗流的問題,但IDK在使用文件時如何修復它... – 2013-05-08 18:51:47

0

好吧,它現在是固定的。感謝馬克的迴應,我覺得它應該如何工作。 這裏是工作的代碼,如果有人以後會需要它:

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

也許它並不完美的代碼(我知道這可能是多餘的),但即使是大文件的罰款。

0

這個問題是相當古老的,但它值得更好的解釋。該問題隱藏在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(); 
}