views:

48

answers:

1

This is a segment of code I have for setting the masterpassword:

private void button1_Click(object sender, EventArgs e)
    {
        string current = textBox1.Text;
        string newPass = textBox2.Text;
        string confirmed = textBox3.Text;
        string massPass = "winxp.pma";


        if (File.Exists(massPass))
        {
            byte[] cipertext = File.ReadAllBytes(massPass);
            string decoded;
            if(Encryptor.TryDecrypt(current, cipertext, out decoded))
            {
                FileStream fs = new FileStream(massPass, FileMode.Truncate, FileAccess.Write);
                StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);
                if(newPass == confirmed)
                {
                    byte[] newCipher = Encryptor.Encrypt(newPass, newPass);
                    string writeIt = System.Text.Encoding.UTF8.GetString(newCipher);
                    sw.Write(writeIt);
                    sw.Flush();
                    sw.Close();
                    fs.Close();
                    this.Close();

                }
                else
                {
                    MessageBox.Show("New password do not match.", "Error", MessageBoxButtons.OK);
                }

            }

        }
        else
        {
            FileStream fs = new FileStream(massPass, FileMode.Create, FileAccess.Write);
            StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);
            if (newPass == confirmed)
            {
                byte[] ciphertext = Encryptor.Encrypt(newPass, newPass);
                string writeIt = System.Text.Encoding.UTF8.GetString(ciphertext);
                sw.Write(ciphertext);
                sw.Flush();
                sw.Close();
                fs.Close();
                this.Close();
            }

Back on the main form, I'm using the TryDecrypt method in the following manner:

private void S_Click(object sender, EventArgs e)
    {
        byte[] ciphertext = File.ReadAllBytes(massPass);
        string decoded;

            if (Encryptor.TryDecrypt(textBox1.Text, ciphertext, out decoded))
            {
                accountGroupsBox.Enabled = true;
                addNewPasswordToolStripMenuItem.Enabled = true;
                label2.Text = "Interface Unlocked";

            }
            else
            {
                MessageBox.Show("Incorrect Master Password.", "Authentication Error", MessageBoxButtons.OK);
            }

However, as I noted, it will not return true....I'm betting it something to do with the way I'm handling the FileStreams on the other form, but I dont understand enough whats happening under the hood to determine if I'm doing it correctly.

A: 

Your input stream isn't complete. To be able to attempt to decrypt it, it must be a certain size. Ensure that your encryption process is correct. The encrypted data should be equal to or longer than your plain data.

[edit]
My conclusion back on the other site was that the CryptoStream did not have a chance to finish writing the data before your output file was closed. The output stream should remain open before the CryptoStream is disposed to be able to write the rest of the ciphertext and necessary padding.

My test code:

public static byte[] Encrypt(string password, string plaintext, SymmetricAlgorithm algorithm)
{
    byte[] key, iv;
    CreateKeyIV(password, out key, out iv);
    using (MemoryStream encrypted = new MemoryStream())
    {
        using (CryptoStream enc = new CryptoStream(encrypted, algorithm.CreateEncryptor(key, iv), CryptoStreamMode.Write))
        using (StreamWriter writer = new StreamWriter(enc))
            writer.Write(plaintext);
        return encrypted.ToArray();
    }
}
Jeff M
Are you even checking for replies in your other posts at other sites? :)
Jeff M
Oh I hadn't check debugging in several days...I assumed it was a relatively inactive sight. That code you posted up there....I would want to change the memory streams to be FileStreams for my purposes correct?
Stev0
Yeah it generally is. A lot that's there is people looking for homework help from the generous few that answers regularly (3-4 people including myself). All out of love though. ;) -- A move to using a memory stream will make this process much quicker and more secure as you don't have to work with temporary files and all the problems dealing with those can bring. To summarize what I mentioned at Debugging, make sure you close the CryptoStream before you accept the encrypted data.
Jeff M
Taking a more in depth look at your code, I am following how this would work for a file containing a single word of text....but what about for the XML file? I understand the File.ReadAllText() method....does that work for XML in the same capacity so you can pass it to a memory stream?
Stev0
The File.ReadAllText() method reads the entire text file and returns the contents into a string. That includes newline characters and whatnot. This works fine for text files but not necessarily for binary files. I only did this to make the test program easier to write as a demonstration. I'll update this post with the relevant code.
Jeff M
Ah sweet thanks. I tried doing it on my own and screwed the pooch. I was using byte[] ciphertext = File.ReadAllBytes(masterpasswordfile), then passing that into TryDecrypt, and it would not pass, so I'm assuming I'm reading the file wrong. I'll throw in the new code I've worked up, see if you can figure out what I did wrong.
Stev0