Exception thrown when decrypting read-in message from file

C

chau_fai

i got two buttons in the form. One is for encrypting the message read
from a xml file and then encrypt the xml and save back to another
file. The other button is for decryption. Again, this button read the
encrypted file back, and then perform decryption.
But i don't know why an exception always thrown when processing this
line of code "int actualbytesread = encStream.Read(buf, 0, 100);" ...
Can anyone give me some instructions what is happening ?

private void Encrypt_Click(object sender, System.EventArgs e)
{
XmlDocument xml = new XmlDocument();
xml.Load(Application.StartupPath + "\\Data\\userInfo.xml");

Byte[] data = new UnicodeEncoding().GetBytes(xml.OuterXml);
MemoryStream ms = new MemoryStream(data.Length* 2);

DES des = new DESCryptoServiceProvider() ;

CryptoStream encStream = new CryptoStream(ms,des.CreateEncryptor(),
CryptoStreamMode.Write);

encStream.Write(data, 0, data.Length);
encStream.FlushFinalBlock();


//calculate the length of the encrypted data
byte[] bResult = new byte[ms.Position];
ms.Position = 0;
ms.Read(bResult, 0, bResult.Length) ;
FileStream fs = new FileStream(Application.StartupPath +
"\\Data\\file.try", FileMode.OpenOrCreate, FileAccess.ReadWrite,
FileShare.None);
fs.Write(bResult, 0, bResult.Length);
fs.Close();
}

private void Decrypt_Click(object sender, System.EventArgs e)
{
FileStream fs= new FileStream(Application.StartupPath +
"\\Data\\file.try", FileMode.Open, FileAccess.Read, FileShare.None);

byte[] ByteArray=new byte[fs.Length];
int nBytesRead = fs.Read(ByteArray, 0, ByteArray.Length);
fs.Close();

MemoryStream ms = new MemoryStream(ByteArray);

DES des = new DESCryptoServiceProvider();
CryptoStream encStream = new CryptoStream(ms,
des.CreateDecryptor(), CryptoStreamMode.Read);

MemoryStream plaintextmem = new MemoryStream();

do
{
Byte[] buf = new Byte[100];

try
{
//read the plaintext from CryptoStream
int actualbytesread = encStream.Read(buf, 0, 100);

//if we have reached the end of stream quit the loop
if (0 == actualbytesread)
break;

//copy the plaintext byte array to MemoryStream
plaintextmem.Write(buf,0,actualbytesread);
}
catch(Exception ab)
{
MessageBox.Show(ab.Message, "Asdf");
}
}while(true);

encStream.Close();
ms.Close();

//Extract the plaintext byte stream and close the MemoryStream
Byte[] plaintextbyte = plaintextmem.ToArray();
plaintextmem.Close();

//Encode the plaintext byte into Unicode string
string plaintext = new UnicodeEncoding().GetString(plaintextbyte);

encStream.Close();
}

In the try-catch block, these errors are showed when i list it out

"Data Error"
Mscorlib (in Mscorlib.dll)
at System.Security.Cryptography.CryptoAPITransform._DecryptData(IntPtr
hKey, Byte[] rgb, Int32 ib, Int32 cb, Boolean fDone)
at System.Security.Cryptography.CryptoAPITransform.TransformFinalBlock(Byte[]
inputBuffer, Int32 inputOffset, Int32 inputCount)
at System.Security.Cryptography.CryptoStream.Read(Byte[] buffer,
Int32 offset, Int32 count)
at WindowsApplication3.Form1.button10_Click(Object sender, EventArgs
e)

I would appreciate any response and help from yours ~
 
J

Jon Skeet [C# MVP]

chau_fai said:
i got two buttons in the form. One is for encrypting the message read
from a xml file and then encrypt the xml and save back to another
file. The other button is for decryption. Again, this button read the
encrypted file back, and then perform decryption.
But i don't know why an exception always thrown when processing this
line of code "int actualbytesread = encStream.Read(buf, 0, 100);" ...
Can anyone give me some instructions what is happening ?

Well, you've got a few problems here, and a few oddities:

1) You don't need to create a new UnicodeEncoding each time - just the
Encoding.Unicode property is fine.

2) Why are you creating a memory stream with twice the data size?

3) When you create the crypto service provider and then the subsequent
encryptor or decryptor, you're never specifying the key or
initialization vector, so a random one of each is assigned. This is
probably the main cause of your problem.

4) A much easier way of turning a MemoryStream into a byte array is
just to call ToArray.

5) Using the "using" construct around all streams means they'll be
closed automatically if an exception is thrown - if the write to the
file fails in your code, for instance, you won't end up closing the
stream.

6) Rather than creating a byte array of the same size as the file, and
then creating a memory stream from that, why not just pass the
FileStream into the constructor of the CryptoStream?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top