2011-03-01 37 views
1

當我使用錯誤的密鑰時,我得到一個「解密的」垃圾文件和mscorlib.dll的異常,「指定的塊大小對此算法無效」。我想要的是解密完全失敗而不拋出異常。如何使用Rijndael解密文件來確定密鑰或向量不正確?

這裏是我當前的代碼(改編自vb.net的例子,我發現在互聯網上,所以更好的解決辦法,如果在那裏可以理解的)

public static bool EncryptOrDecryptFile(string strInputFile, 
     string strOutputFile, string pKey, string pIv, CryptoAction Direction) 
    { 
     Byte[] bytKey = CreateKey(pKey); 
     Byte[] bytIV = CreateIV(pIv); 
     bool pRet = false; 
     if (!File.Exists(strInputFile)) 
      return false; 

     try 
     { 
      using (FileStream fsInput = new FileStream(strInputFile, FileMode.Open, FileAccess.Read)) 
      { 
       using (FileStream fsOutput = new FileStream(strOutputFile, FileMode.OpenOrCreate, FileAccess.Write)) 
       { 
        fsOutput.SetLength(0); 
        byte[] bytBuffer = new byte[4097]; 
        long lngBytesProcessed = 0; 
        long lngFileLength = fsInput.Length; 
        int intBytesInCurrentBlock = 0; 
        CryptoStream csCryptoStream = null; 
        RijndaelManaged cspRijndael = new RijndaelManaged(); 
        cspRijndael.BlockSize = 4096; 
        switch (Direction) 
        { 
         case CryptoAction.ActionEncrypt: 
          csCryptoStream = new CryptoStream(fsOutput, cspRijndael.CreateEncryptor(bytKey, bytIV), 
                   CryptoStreamMode.Write); 
          break; 
         case CryptoAction.ActionDecrypt: 
          csCryptoStream = new CryptoStream(fsOutput, cspRijndael.CreateDecryptor(bytKey, bytIV), 
                   CryptoStreamMode.Write); 
          break; 
        } 
        while (lngBytesProcessed < lngFileLength) 
        { 
         intBytesInCurrentBlock = fsInput.Read(bytBuffer, 0, 4096); 
         csCryptoStream.Write(bytBuffer, 0, intBytesInCurrentBlock); 
         lngBytesProcessed = lngBytesProcessed + Convert.ToInt64(intBytesInCurrentBlock); 
        } 
        csCryptoStream.Close(); 
       } 
      } 
      pRet = true; 
     } 
     catch (Exception ex) 
     { 
      pRet = false; 
     } 
     return pRet; 
    } 
    #endregion 
} 

回答

1

考慮到合適的長度的位的任何組合可是一個有效的密鑰,並且對於IV也是如此,密碼流無法確定這是否是不正確的,直到它試圖解密密碼文本的最後一塊爲止 - 在這一點上它檢測到填充是錯誤的並且拋出異常。此外,你不能使用任何塊大小,你想要的 - 有某些塊大小是有效的特定加密提供商 - Rijndael,我認爲有效的塊大小是128,192和256.

唯一的方法來避免「垃圾」文件將執行內存中的所有解密操作,或寫入臨時文件而不是最終輸出文件。無法避免這種異常,但無論如何這應該是一個不尋常的事情。


我也得到你的代碼擺脫所有的緩衝區管理的,和長度檢查等,並只使用Stream.CopyTo你的輸入流和密碼流之間。例如: -

using (FileStream fsInput = new FileStream(strInputFile, FileMode.Open, FileAccess.Read)) 
{ 
    using (FileStream fsOutput = new FileStream(strOutputFile, FileMode.OpenOrCreate, FileAccess.Write)) 
    { 
     CryptoStream csCryptoStream = null; 
     RijndaelManaged cspRijndael = new RijndaelManaged(); 
     cspRijndael.BlockSize = 256; 
     switch (Direction) 
     { 
      case CryptoAction.ActionEncrypt: 
       csCryptoStream = new CryptoStream(fsOutput, cspRijndael.CreateEncryptor(bytKey, bytIV), 
                CryptoStreamMode.Write); 
       break; 
      case CryptoAction.ActionDecrypt: 
       csCryptoStream = new CryptoStream(fsOutput, cspRijndael.CreateDecryptor(bytKey, bytIV), 
                CryptoStreamMode.Write); 
       break; 
     } 
     fsInput.CopyTo(csCryptoStream); 
     csCryptoStream.Close(); 
    } 
} 
pRet = true; 
+0

謝謝。如何在dotnet 3.5中執行filestream CopyTo? – cabgef 2011-03-01 13:42:45

+0

@mikeh - 我會在Stream上創建一個擴展方法,並將這個問題的答案複製到它:http://stackoverflow.com/questions/1933742/how-is-the-stream-copytostream-method-implemented- in-net-4 – 2011-03-01 13:44:22

+0

對於不正確的IV /密鑰,不能保證填充例外。 – 2011-03-02 00:48:34

1

無可用的modes of operationRijndaelManaged提供完整性保護或認證。依靠檢查填充的有效性不能替代,因爲使用有效的填充可以輕鬆獲得錯誤的消息。

相反,您應該將HMAC應用於加密郵件。

相關問題