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;
}
-
For a start, this while loop condition is never right:
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, theEncoding.Unicode
property means you don't have to create a newUnicodeEncoding
yourself. Also, I generally find that setting thePosition
property is more readable than usingSeek
. Finally, there's no point in a method returning a value if it's always going to betrue
. So, your code would become: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.
veagles : Thanks, that was just a rough code. I have made the changes as suggested. I am still getting the same exception in CopyStream(cryptoStream, s_DecryptedStream);Jon Skeet : Then please post a short but complete program which demonstrates the problem. Something we can run to reproduce it.veagles : It worked.. It ways my mistake.. Thanks anyways. -
You may need to call the FlushFinalBlock method on the CryptoStream after you have finished reading the input data. (ie. crytpoStream.FlushFinalBlock() after CopyStream)
Jon Skeet : I think you *shouldn't* need to do that if you dispose of the CryptoStream - there was a bug in .NET 1.1 which meant that it didn't flush the final block then, but it was fixed in .NET 2.0.Sam : Ahh, ok, just me following old code examples then. -
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
0 comments:
Post a Comment