2009-05-10 41 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

相关问题