views:

284

answers:

3

OK, my need here is to save whatever typed in the rich text box to a file, encrypted, and also retrieve the text from the file again and show it back on the rich textbox. Here is my save code.

private void cmdSave_Click(object sender, EventArgs e)
{
    FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write);

    AesCryptoServiceProvider aes = new AesCryptoServiceProvider();

    aes.GenerateIV();
    aes.GenerateKey();
    aes.Mode = CipherMode.CBC;

    TextWriter twKey = new StreamWriter("key");
    twKey.Write(ASCIIEncoding.ASCII.GetString(aes.Key));
    twKey.Close();

    TextWriter twIV = new StreamWriter("IV");
    twIV.Write(ASCIIEncoding.ASCII.GetString(aes.IV));
    twIV.Close();

    ICryptoTransform aesEncrypt = aes.CreateEncryptor();

    CryptoStream cryptoStream = new CryptoStream(fs, aesEncrypt, CryptoStreamMode.Write);

    richTextBox1.SaveFile(cryptoStream, RichTextBoxStreamType.RichText);
}

I know the security consequences of saving the key and iv in a file but this just for testing :)

Well, the saving part works fine which means no exceptions... The file is created in filePath and the key and IV files are created fine too...

OK now for retrieving part where I am stuck :S

private void cmdOpen_Click(object sender, EventArgs e)
{
    OpenFileDialog openFile = new OpenFileDialog();

    openFile.ShowDialog();

    FileStream openRTF = new FileStream(openFile.FileName, FileMode.Open, FileAccess.Read);

    AesCryptoServiceProvider aes = new AesCryptoServiceProvider();

    TextReader trKey = new StreamReader("key");
    byte[] AesKey = ASCIIEncoding.ASCII.GetBytes(trKey.ReadLine());

    TextReader trIV = new StreamReader("IV");
    byte[] AesIV = ASCIIEncoding.ASCII.GetBytes(trIV.ReadLine());

    aes.Key = AesKey;
    aes.IV = AesIV;

    ICryptoTransform aesDecrypt = aes.CreateDecryptor();

    CryptoStream cryptoStream = new CryptoStream(openRTF, aesDecrypt, CryptoStreamMode.Read);

    StreamReader fx = new StreamReader(cryptoStream);

    richTextBox1.Rtf = fx.ReadToEnd();

    //richTextBox1.LoadFile(fx.BaseStream, RichTextBoxStreamType.RichText);        
} 

But the richTextBox1.Rtf = fx.ReadToEnd(); throws an cryptographic exception "Padding is invalid and cannot be removed."

while richTextBox1.LoadFile(fx.BaseStream, RichTextBoxStreamType.RichText); throws an NotSupportedException "Stream does not support seeking."

Any suggestions on what i can do to load the data from the encrypted file and show it in the rich text box?

+1  A: 

Since you never closed the CryptoStream in Save, it never called FlushFinalBlock to finish writing the data. Therefore, not all of the data was saved.

SLaks
My first answer was wrong.
SLaks
+1  A: 

Your IV and Key are never written in the file to begin with (judging from your save_cmd)

And same goes for your opening. There's no link at ALL between between your ("Key" stream and your file anywhere...)

Updated :

Here is a better version of your code :

        private void button1_Click(object sender, EventArgs e)
    {


        AesCryptoServiceProvider aes = new AesCryptoServiceProvider();

        aes.GenerateIV();
        aes.GenerateKey();
        aes.Mode = CipherMode.CBC;


        File.WriteAllBytes("Key",aes.Key);
        File.WriteAllBytes("IV",aes.IV);


        ICryptoTransform aesEncrypt = aes.CreateEncryptor();
        using (FileStream fs = new FileStream("file.crypt", FileMode.Create, FileAccess.Write))
        {
            using (CryptoStream cryptoStream = new CryptoStream(fs, aesEncrypt, CryptoStreamMode.Write))
            {

                richTextBox1.SaveFile(cryptoStream, RichTextBoxStreamType.RichText);
            }
        }

    }

       private void button2_Click(object sender, EventArgs e)
    {
        OpenFileDialog openFile = new OpenFileDialog();

        openFile.ShowDialog();



        AesCryptoServiceProvider aes = new AesCryptoServiceProvider();


        byte[] AesKey = File.ReadAllBytes("Key");
        byte[] AesIV = File.ReadAllBytes("IV");

        aes.Key = AesKey;
        aes.IV = AesIV;

        ICryptoTransform aesDecrypt = aes.CreateDecryptor();
        using (FileStream openRTF = new FileStream(openFile.FileName, FileMode.Open, FileAccess.Read))
        {
            using (CryptoStream cryptoStream = new CryptoStream(openRTF, aesDecrypt, CryptoStreamMode.Read))
            {

                using (StreamReader fx = new StreamReader(cryptoStream))
                {
                    richTextBox1.Rtf = fx.ReadToEnd();
                }
            }
        }

    }

It works.

Jipy
The key and the IV are written separately to two different files using twKey and twIV which are TextWriter's. ("key" and "IV", these two are files without any extension) TextWriter twKey = new StreamWriter("key"); twKey.Write(ASCIIEncoding.ASCII.GetString(aes.Key)); twKey.Close();and the same key and file are loaded back in using the TextReader as well.
Ranhiru Cooray
Wrong; I made the same mistake at first. He's creating two files named `Key` and `IV`.
SLaks
Yes you are right! I was wrong in assuming that the key is loaded properly :( It is actually different key and iv when it is loaded...How do i properly write and retrieve the key from a file?
Ranhiru Cooray
Updated the post with your answer ( File.ReadAllBytes and File.WriteAllBytes was what you needed)
Jipy
A: 

OK, i achieved perfectly what i wanted to achieve. There were several key failures in my code... First, thanx to SLaks and Jipy i figured out that "thou shall close all streams that were open" :)

And the second major blunder i did was trying to save the key and iv in a file where actually saving or loading it back did not work! Thus i just had two byte[] to save the key and IV

I changed the padding scheme to ISO10126 and made sure that the Mode was CBC when both opening and closing commands.

And else i had to do was add the code to open command and it worked :) :) :)

        StreamReader fx = new StreamReader(cryptoStream);

        fx.Read(fileContent, 0, Convert.ToInt32(fileContent.Length));

        fx.Close();

        cryptoStream.Close();

        richTextBox1.Rtf = new String(fileContent);

Anyway any other stupid performance issues are welcome :)

Here is the complete open and close commands to anyone who is interested.

    byte[] globalKey = new byte[32];
    byte[] globalIV = new byte[16];

    private void cmdSave_Click(object sender, EventArgs e)
    {


        FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write);

        AesCryptoServiceProvider aes = new AesCryptoServiceProvider();

        aes.GenerateIV();
        aes.GenerateKey();
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.ISO10126;

        globalKey = aes.Key;
        globalIV = aes.IV;


        ICryptoTransform aesEncrypt = aes.CreateEncryptor();

        CryptoStream cryptoStream = new CryptoStream(fs, aesEncrypt, CryptoStreamMode.Write);

        richTextBox1.SaveFile(cryptoStream, RichTextBoxStreamType.RichText);

        cryptoStream.Close();
        fs.Close();

        richTextBox1.Clear();


    }

    private void cmdOpen_Click(object sender, EventArgs e)
    {
        OpenFileDialog openFile = new OpenFileDialog();

        openFile.ShowDialog();

        FileStream openRTF = new FileStream(openFile.FileName, FileMode.Open, FileAccess.Read);

        AesCryptoServiceProvider aes = new AesCryptoServiceProvider();


        aes.Key = globalKey;
        aes.IV = globalIV;
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.ISO10126;


        ICryptoTransform aesDecrypt = aes.CreateDecryptor();

        CryptoStream cryptoStream = new CryptoStream(openRTF, aesDecrypt, CryptoStreamMode.Read);

        FileInfo fileNFO = new FileInfo(openFile.FileName);

        char[] fileContent = new char[fileNFO.Length];

        StreamReader fx = new StreamReader(cryptoStream);

        fx.Read(fileContent, 0, Convert.ToInt32(fileContent.Length));

        fx.Close();

        cryptoStream.Close();

        richTextBox1.Rtf = new String(fileContent); 



    } 
Ranhiru Cooray