2012-03-15 53 views
4

我遇到一些麻煩,下面的代碼可以在讀取。我有一個需要加密的臨時位置的文件,這個函數會加密那些存儲在「pathToSave」位置的數據。從CryptoStream就到流

在檢查似乎並沒有被正確地處理整個文件 - 有從我的輸出失位,我懷疑它做的,而不是循環在整個流運行。

順便說一句,如果我嘗試和while循環後調用CryptStrm.Close()我收到一個異常。這意味着如果我試圖解密文件,我得到一個已經在使用中的文件錯誤!

嘗試了所有的常用和伊夫這裏看着在類似的問題,任何幫助將是巨大的。

感謝

public void EncryptFile(String tempPath, String pathToSave) 
    { 
     try 
     { 
      FileStream InputFile = new FileStream(tempPath, FileMode.Open, FileAccess.Read); 
      FileStream OutputFile = new FileStream(pathToSave, FileMode.Create, FileAccess.Write); 

      RijndaelManaged RijCrypto = new RijndaelManaged(); 

      //Key 
      byte[] Key = new byte[32] { ... }; 

      //Initialisation Vector 
      byte[] IV = new byte[32] { ... }; 

      RijCrypto.Padding = PaddingMode.None; 
      RijCrypto.KeySize = 256; 
      RijCrypto.BlockSize = 256; 
      RijCrypto.Key = Key; 
      RijCrypto.IV = IV; 

      ICryptoTransform Encryptor = RijCrypto.CreateEncryptor(Key, IV); 

      CryptoStream CryptStrm = new CryptoStream(OutputFile, Encryptor, CryptoStreamMode.Write); 

      int data; 
      while (-1 != (data = InputFile.ReadByte())) 
      { 
       CryptStrm.WriteByte((byte)data); 
      } 
     } 
     catch (Exception EncEx) 
     { 
      throw new Exception("Encoding Error: " + EncEx.Message); 
     } 
    } 

編輯:

我所做的假設,我的問題是加密。我的解密可能是罪魁禍首

 public String DecryptFile(String encryptedFilePath) 
    { 
     FileStream InputFile = new FileStream(encryptedFilePath, FileMode.Open, FileAccess.Read); 

     RijndaelManaged RijCrypto = new RijndaelManaged(); 

     //Key 
     byte[] Key = new byte[32] { ... }; 

     //Initialisation Vector 
     byte[] IV = new byte[32] { ... }; 

     RijCrypto.Padding = PaddingMode.None; 
     RijCrypto.KeySize = 256; 
     RijCrypto.BlockSize = 256; 
     RijCrypto.Key = Key; 
     RijCrypto.IV = IV; 

     ICryptoTransform Decryptor = RijCrypto.CreateDecryptor(Key, IV); 

     CryptoStream CryptStrm = new CryptoStream(InputFile, Decryptor, CryptoStreamMode.Read); 

     String OutputFilePath = Path.GetTempPath() + "myfile.name"; 
     StreamWriter OutputFile = new StreamWriter(OutputFilePath); 

     OutputFile.Write(new StreamReader(CryptStrm).ReadToEnd()); 

     CryptStrm.Close(); 
     OutputFile.Close(); 

     return OutputFilePath; 
    } 

回答

12

好吧,這裏有幾件事情出錯了。

1.您設置IV過大的尺寸。如果您的密鑰大小爲256,Rijndael的IV爲16個字節。如果您嘗試使用比該字節更多的字節來設置密鑰,則會發生異常。 IV尺寸應設置爲塊尺寸/ 8 see MSDN,因此您擁有的IV尺寸是正確的。

  • 您有無的填充模式。除非你的數據是正確的塊大小,否則你將會遇到問題。您可能想要選擇填充模式。
  • 當您在加密時寫入密碼流時,通常需要調用FlushFInalBlock以確保將所有數據寫入流中。
  • 我發佈了一些示例代碼,使用內存流來顯示加密和解密。

    var tempData = "This is the text to encrypt. It's not much, but it's all there is."; 
    
    using (var rijCrypto = new RijndaelManaged()) 
    { 
        byte[] encryptedData; 
        rijCrypto.Padding = System.Security.Cryptography.PaddingMode.ISO10126; 
        rijCrypto.KeySize = 256; 
    
        using (var input = new MemoryStream(Encoding.Unicode.GetBytes(tempData))) 
        using (var output = new MemoryStream()) 
        { 
         var encryptor = rijCrypto.CreateEncryptor(); 
    
         using (var cryptStream = new CryptoStream(output, encryptor, CryptoStreamMode.Write)) 
         { 
          var buffer = new byte[1024]; 
          var read = input.Read(buffer, 0, buffer.Length); 
          while (read > 0) 
          { 
           cryptStream.Write(buffer, 0, read); 
           read = input.Read(buffer, 0, buffer.Length); 
          } 
          cryptStream.FlushFinalBlock(); 
          encryptedData = output.ToArray(); 
         } 
        } 
    
        using (var input = new MemoryStream(encryptedData)) 
        using (var output = new MemoryStream()) 
        { 
         var decryptor = rijCrypto.CreateDecryptor(); 
         using (var cryptStream = new CryptoStream(input, decryptor, CryptoStreamMode.Read)) 
         { 
          var buffer = new byte[1024]; 
          var read = cryptStream.Read(buffer, 0, buffer.Length); 
          while (read > 0) 
          { 
           output.Write(buffer, 0, read); 
           read = cryptStream.Read(buffer, 0, buffer.Length); 
          } 
          cryptStream.Flush(); 
          var result = Encoding.Unicode.GetString(output.ToArray()); 
         } 
        } 
    } 
    
    +0

    謝謝pstrjds - 我做了一些改變,但仍然有問題。 IV現在是16個字節,填充是零,我已經改變了我的while循環,看起來更像是你的建議,但當我調用FlushFinalBlock時,我仍然得到錯誤 - 「方法在CryptoStream上調用兩次,只能調用一次」 。儘管如此,我不相信它已被稱爲第一位! – David 2012-03-16 09:15:44

    +0

    那麼,你應該只在調用循環之外調用FlushFinalBlock作爲加密時的最後一件事。你不需要在解密時調用它,解密時只需調用Flush。當你解密時你的塊大小應該是正確的,所以不需要添加任何填充。就相信它是否被調用而言,您可以在調試器下運行您的代碼並在該行設置一箇中斷點。如果它沒有擊中它,那麼它不會被調用。 – pstrjds 2012-03-16 12:48:39

    +1

    _如果你的密鑰大小爲256,Rijndael的IV是16個字節。如果你試圖設置比這個字節更多的字節,你將會得到一個異常。如果你有'BlockSize = 256',那麼你的IV應該是32,這是不正確的。如果它們不匹配,那麼你將得到一個例外。 – Trisped 2013-03-02 05:00:05