2009-05-10 76 views
4

我得到「要解密的數據的長度無效。」例外,當我嘗試解密一個內存流。我是初學者,無法弄清楚什麼是錯的。怎麼了?」要解密的數據的長度無效。「 Rijndael解密期間的例外

public bool EncryptStream() 
    { 

     string password = @"myKey123"; // Your Key Here 
     UnicodeEncoding UE = new UnicodeEncoding(); 
     byte[] key = UE.GetBytes(password); 

     s_EncryptedStream = new MemoryStream(); 
     int NoOfBytes; 
     byte[] b_Buffer = new byte[8192]; 

     s_MemoryStream.Seek(0, SeekOrigin.Begin); 

     RijndaelManaged RMCrypto = new RijndaelManaged(); 

     s_CrytpoStream = new CryptoStream(s_EncryptedStream, 
      RMCrypto.CreateEncryptor(key, key), 
      CryptoStreamMode.Write); 

     while (s_MemoryStream.Length < s_MemoryStream.Position) 
     { 
      NoOfBytes = s_MemoryStream.Read(b_Buffer, 0, 8192); 
      s_CrytpoStream.Write(b_Buffer, 0, NoOfBytes); 
     } 

     s_MemoryStream.Seek(0, SeekOrigin.Begin); 

     while (s_EncryptedStream.Position < s_EncryptedStream.Length) 
     { 
      NoOfBytes = s_EncryptedStream.Read(b_Buffer, 0, 8192); 
      s_MemoryStream.Write(b_Buffer, 0, NoOfBytes); 

     } 
     s_CrytpoStream.Flush(); 
     s_CrytpoStream.Close(); 

     return true; 

    } 


    public bool DecryptStream() 
    { 


     string password = @"myKey123"; // Your Key Here 

     UnicodeEncoding UE = new UnicodeEncoding(); 
     byte[] key = UE.GetBytes(password); 

     int NoOfBytes; 
     byte[] b_Buffer = new byte[8192]; 

     s_DecryptedStream = new MemoryStream(); 


     RijndaelManaged RMCrypto = new RijndaelManaged(); 

     s_CrytpoStream = new CryptoStream(s_MemoryStream, 
      RMCrypto.CreateDecryptor(key, key), 
      CryptoStreamMode.Read); 

     s_MemoryStream.Seek(0, SeekOrigin.Begin); 

     while (s_MemoryStream.Length > s_MemoryStream.Position) 
     { 
      NoOfBytes = s_CrytpoStream.Read(b_Buffer, 0, 8192); 
      s_DecryptedStream.Write(b_Buffer, 0, NoOfBytes); 
     } 

     s_DecryptedStream.Seek(0, SeekOrigin.Begin); 
     s_MemoryStream.Seek(0, SeekOrigin.Begin); 

     while (s_DecryptedStream.Position < s_DecryptedStream.Length) 
     { 
      NoOfBytes = s_DecryptedStream.Read(b_Buffer, 0, 8192); 
      s_MemoryStream.Write(b_Buffer, 0, NoOfBytes); 

     } 

     s_CrytpoStream.Flush(); 
     s_CrytpoStream.Close(); 

     return true; 

    } 

回答

6

一開始,這個while循環的條件是永遠正確的:

while (s_MemoryStream.Length < s_MemoryStream.Position) 

的位置如何能超越長度是多少?

而不是使用流的長度,複製流的通常模式是重複讀取,直到返回的值不是正數。正如你在這個代碼這樣做兩次,無論如何,你還不如將其封裝:

public static void CopyStream(Stream input, Stream output) 
{ 
    byte[] buffer = new byte[8192]; 
    int read; 
    while ((read = input.Read(buffer, 0, buffer.Length)) > 0) 
    { 
     output.Write(buffer, 0, read); 
    } 
} 

這也是最好使用using語句來清理字符串。此外,Encoding.Unicode屬性意味着您不必自己創建新的UnicodeEncoding。另外,我通常發現設置Position屬性比使用Seek更具可讀性。最後,如果方法始終爲true,則返回值的方法毫無意義。所以,你的代碼會變成:

public void EncryptStream() 
{ 
    string password = @"myKey123"; // Your Key Here 
    byte[] key = Encoding.Unicode.GetBytes(password); 

    s_EncryptedStream = new MemoryStream(); 
    s_MemoryStream.Position = 0; 

    RijndaelManaged RMCrypto = new RijndaelManaged(); 

    using (Stream crytpoStream = new CryptoStream(s_EncryptedStream, 
     RMCrypto.CreateEncryptor(key, key), 
     CryptoStreamMode.Write)) 
    { 
     CopyStream(s_MemoryStream, cryptoStream); 
    } 

    s_MemoryStream.Position = 0; 
    s_EncryptedStream.Position = 0; 
    CopyStream(s_EncryptedStream, s_MemoryStream); 
} 

public void DecryptStream() 
{ 
    string password = @"myKey123"; // Your Key Here 
    byte[] key = Encoding.Unicode.GetBytes(password); 

    s_DecryptedStream = new MemoryStream(); 
    s_MemoryStream.Position = 0; 

    RijndaelManaged RMCrypto = new RijndaelManaged(); 

    using (Stream crytpoStream = new CryptoStream(s_MemoryStream, 
     RMCrypto.CreateDecryptor(key, key), 
     CryptoStreamMode.Read)) 
    { 
     CopyStream(cryptoStream, s_DecryptedStream); 
    } 

    s_DecryptedStream.Position = 0; 
    s_MemoryStream.Position = 0; 

    CopyStream(s_DecryptedStream, s_MemoryStream); 
} 

即使修改了這段代碼,感覺你在這裏有太多的非局部變量。我看不出爲什麼這個應該是在實例變量中的任何。使流加密或解密一個參數(以及密碼),並返回一個帶有加密/解密數據的內存流,或者只是一個字節數組。

+0

謝謝,這只是一個粗略的代碼。我已經按照建議進行了更改。 我仍然在CopyStream(cryptoStream,s_DecryptedStream)中得到相同的異常; – veagles 2009-05-10 20:41:10

+0

然後請發佈一個簡短但完整的程序來演示問題。我們可以運行它來重現它。 – 2009-05-10 21:07:27

+0

它的工作..它的方式我的錯誤..謝謝反正。 – veagles 2009-05-11 06:32:39

1

讀完輸入數據後,您可能需要在CryptoStream上調用FlushFinalBlock方法。 (即crytpoStream.FlushFinalBlock()後CopyStream)

+0

我認爲如果你處理CryptoStream,你*不應該那樣做 - 在.NET 1.1中存在一個錯誤,這意味着它沒有刷新最後的塊,但它在.NET 2.0中得到了修復。 – 2009-05-10 21:08:05

+0

啊,好吧,只需要我遵循舊的代碼示例。 – Sam 2009-05-11 16:44:34

0

我想出了一個解決方案,我把它貼在我的新博客

constotech.blogspot.com/2009/05/net-encryption-using-symmetricalgorithm.html

相關問題