views:

90

answers:

2

Ok so at this point I've figured out many of the other issues I was having. Now upon attempting to decrypt the file, I receive no exceptions, however the data is not decrypted properly....it goes through the entire operation without throwing an exception, until I attempt to access the XML document via the combo box again after decrypting. At which time this error is thrown:

Unexpected end of file has occurred. The following elements are not closed: Account. Line 12, position 10. when I open the file in a web browser it only has like 1 half of an XML Node. What happened?

public partial class Form1 : Form
{
    public string fileName = "passfile.xml";
    public DataSet ds = new DataSet("Account List");
    public DataTable accounts = new DataTable("Accounts");
    public Form1()
    {
        InitializeComponent();
        accountGroupsBox.Enabled = false;
        menuStrip1.Enabled = false;
        button2.Enabled = false;
        Types type = new Types();
        this.accountGroupsBox.Items.AddRange(type.accountTypes);
        accounts.Columns.AddRange(new DataColumn[] {
            new DataColumn("Username"),
            new DataColumn("Password"),
            new DataColumn("Description")});

        dataGridView1.DataSource = accounts;


    }

    private void addNewPasswordToolStripMenuItem_Click(object sender, EventArgs e)
    {
        Form2 addAccount = new Form2(this);
        addAccount.Show();
    }

    private void S_Click(object sender, EventArgs e)
    { //Need to add some code to check for password correctness, for now just unlock the interface
        accountGroupsBox.Enabled = true;
        menuStrip1.Enabled = true;
        button2.Enabled = true;
        label2.Text = "Interface Unlocked";
    }

    private void accountGroupsBox_SelectedIndexChanged(object sender, EventArgs e)
    { //Display the accounts on the datagrid
        accounts.Clear();
        XmlDocument doc = new XmlDocument();
        doc.Load(fileName);
        foreach (XmlNode node in doc.GetElementsByTagName("Account"))
        {
            if (node["AccountType"].InnerText == accountGroupsBox.SelectedItem.ToString())
            {
                DataRow row = accounts.Rows.Add(
                node["Username"].InnerText,
                node["Password"].InnerText,
                node["Description"].InnerText);
            }
        }


    }
    public void Encrypt()
    {   
        string temp = Path.GetTempFileName();
        string path = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
        byte[] pword = Encoding.UTF8.GetBytes(textBox1.Text);
        byte[] hash = SHA256.Create().ComputeHash(pword);
        byte[] iv = MD5.Create().ComputeHash(pword);
        byte[] key = hash;

        using(FileStream fsInput = new FileStream(fileName, FileMode.Open, FileAccess.Read))
        using(SymmetricAlgorithm alg = Aes.Create())
        using(ICryptoTransform enc = alg.CreateEncryptor(key, iv))
        using (FileStream fsOutput = new FileStream(temp, FileMode.Create, FileAccess.Write))
        using (CryptoStream cs = new CryptoStream(fsOutput, enc, CryptoStreamMode.Write))
        {
            try
            {
                byte[] byteInput = new byte[fsInput.Length - 1];
                fsInput.Read(byteInput, 0, byteInput.Length);
                cs.Write(byteInput, 0, byteInput.Length);

                FileInfo old = new FileInfo(fileName);
                FileInfo newer = new FileInfo(temp);
                old.Delete();
                newer.MoveTo(Path.Combine(path, fileName));


            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Encryption Error", MessageBoxButtons.OK);

            }
        }


    }
    public void Decrypt()
    {

        byte[] pword = Encoding.UTF8.GetBytes(textBox1.Text);
        byte[] hash = SHA256.Create().ComputeHash(pword);
        byte[] iv = MD5.Create().ComputeHash(pword);
        byte[] key = hash;

        using(FileStream fsInput = new FileStream(fileName, FileMode.Open, FileAccess.Read))
        using(SymmetricAlgorithm alg = Aes.Create())
        using(ICryptoTransform enc = alg.CreateDecryptor(key, iv))
        using (CryptoStream cs = new CryptoStream(fsInput, enc, CryptoStreamMode.Read))
        {
            StreamWriter sw = new StreamWriter(temp);
            sw.Write(new StreamReader(cs).ReadToEnd());
            sw.Flush();
            sw.Close();
        }
        FileInfo encrypted = new FileInfo(fileName);
        FileInfo decrypted = new FileInfo(temp);
        encrypted.Delete();
        decrypted.MoveTo(Path.Combine(path, fileName);
A: 

The Delete and MoveTo operations look to be being performed on open files. Additionally, the decrypt method opens the "filename" file twice. On which line are you getting the exception thrown?

Will A
Same thing, the above answer fixed the portion relating to the encryption, now I'm getting the same exception on teh decrypt, specifically during the Streamwriter sw line, what can I change to fix it?
Stev0
Ok to get around it I just did the same thing as the encrypt method...putting the output into a tempfile then moving renaming....
Stev0
@Stev0: Your problem on instantiating your StreamWriter is you're passing the fileName string to it, rather than the file stream.
Mark H
That was a bit of a typo from the edit. The code has been changed to reflect what I have in the vS project. Its actually passing the temp filename name, and performing a similar move rename operation as to the encrypt method, but the file is coming out corrupted
Stev0
+2  A: 

The old file fileName is still open when you call old.Delete(); It will close when the using { } block ends. Move the file deletion and rename to the end of your Encrypt method.

Mark H
That worked well, thanks. However now I'm getting a cannot create file that already exists exception from the new.MoveTo() portion. How do I fix this?
Stev0
@Stev0 - Can you paste the updated code and a stack trace of the exception to pastebin.com or something. I'm not sure what's causing that.
Mark H
Here is teh link to a pastebin of the exception details:http://pastebin.com/rJ5WPhua
Stev0
That exception is coming from your `accountGroupsBox_SelectedIndexChanged()` method. Doesn't look anything to do with the cryptography - but a case of badly formatted Xml in the file. I'd open the file up and check what that is.
Mark H
Abotu your Xml. Is </Account> by any chance the closing element of the file? This line of your code looks suspicious: `new byte[fsInput.Length - 1];` Is there any particular reason why you're chopping a byte off the end of the input file?
Mark H
Yes actually that is the closing element....that portion of the coed, the -1...I was following a tutorial I found about decrypting and encrypting files....perhaps that doesnt work for XML? What should I be doing instead?
Stev0
The buffer should be the same length as the file. (remove the -1). As it is, you're encrypting a file 1 byte smaller than it should've been, and hence losing data from the end of it.
Mark H