I get "Length of the data to decrypt is invalid." exception when i try to decrypt a memory stream. I am beginner, cant figure out whats wrong. whats wrong?
我得到“要解密的数据长度无效”。当我尝试解密内存流时出现异常。我是初学者,不知道什么是错的。怎么了?
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;
}
3 个解决方案
#1
For a start, this while loop condition is never right:
首先,这个while循环条件永远不对:
while (s_MemoryStream.Length < s_MemoryStream.Position)
How can the position be beyond the length?
这个位置如何超越长度?
Rather than using the length of a stream, the usual pattern to copy a stream is to read repeatedly until the value returned isn't positive. As you're doing that twice in this code anyway, you might as well encapsulate it:
不是使用流的长度,而是复制流的通常模式是重复读取,直到返回的值不为正。正如你在这段代码中两次这样做的那样,你不妨把它封装起来:
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);
}
}
It's also best to use using
statements to clean up strings. Additionally, the Encoding.Unicode
property means you don't have to create a new UnicodeEncoding
yourself. Also, I generally find that setting the Position
property is more readable than using Seek
. Finally, there's no point in a method returning a value if it's always going to be true
. So, your code would become:
最好使用using语句来清理字符串。此外,Encoding.Unicode属性意味着您不必自己创建新的UnicodeEncoding。另外,我通常发现设置Position属性比使用Seek更具可读性。最后,如果一个方法总是变为真,那么返回一个值是没有意义的。所以,你的代码将成为:
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);
}
Even after amending this code, it feels like you've got way too many non-local variables here. I can't see why any of this should be in instance variables. Make the stream to be encrypted or decrypted a parameter (along with the password) and return a memory stream with the encrypted/decrypted data in, or just a byte array.
即使在修改了这段代码之后,感觉就像你在这里有太多的非局部变量。我不明白为什么这个应该在实例变量中。使流加密或解密为参数(连同密码)并返回带有加密/解密数据的内存流,或仅返回字节数组。
#2
You may need to call the FlushFinalBlock
method on the CryptoStream
after you have finished reading the input data. (ie. crytpoStream.FlushFinalBlock()
after CopyStream)
完成读取输入数据后,可能需要在CryptoStream上调用FlushFinalBlock方法。 (即CopyStream之后的crytpoStream.FlushFinalBlock())
#3
I have come up with a solution and I have it posted on my new Blog
我已经提出了一个解决方案,并将其发布在我的新博客上
constotech.blogspot.com/2009/05/net-encryption-using-symmetricalgorithm.html
#1
For a start, this while loop condition is never right:
首先,这个while循环条件永远不对:
while (s_MemoryStream.Length < s_MemoryStream.Position)
How can the position be beyond the length?
这个位置如何超越长度?
Rather than using the length of a stream, the usual pattern to copy a stream is to read repeatedly until the value returned isn't positive. As you're doing that twice in this code anyway, you might as well encapsulate it:
不是使用流的长度,而是复制流的通常模式是重复读取,直到返回的值不为正。正如你在这段代码中两次这样做的那样,你不妨把它封装起来:
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);
}
}
It's also best to use using
statements to clean up strings. Additionally, the Encoding.Unicode
property means you don't have to create a new UnicodeEncoding
yourself. Also, I generally find that setting the Position
property is more readable than using Seek
. Finally, there's no point in a method returning a value if it's always going to be true
. So, your code would become:
最好使用using语句来清理字符串。此外,Encoding.Unicode属性意味着您不必自己创建新的UnicodeEncoding。另外,我通常发现设置Position属性比使用Seek更具可读性。最后,如果一个方法总是变为真,那么返回一个值是没有意义的。所以,你的代码将成为:
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);
}
Even after amending this code, it feels like you've got way too many non-local variables here. I can't see why any of this should be in instance variables. Make the stream to be encrypted or decrypted a parameter (along with the password) and return a memory stream with the encrypted/decrypted data in, or just a byte array.
即使在修改了这段代码之后,感觉就像你在这里有太多的非局部变量。我不明白为什么这个应该在实例变量中。使流加密或解密为参数(连同密码)并返回带有加密/解密数据的内存流,或仅返回字节数组。
#2
You may need to call the FlushFinalBlock
method on the CryptoStream
after you have finished reading the input data. (ie. crytpoStream.FlushFinalBlock()
after CopyStream)
完成读取输入数据后,可能需要在CryptoStream上调用FlushFinalBlock方法。 (即CopyStream之后的crytpoStream.FlushFinalBlock())
#3
I have come up with a solution and I have it posted on my new Blog
我已经提出了一个解决方案,并将其发布在我的新博客上
constotech.blogspot.com/2009/05/net-encryption-using-symmetricalgorithm.html