Using Rijndael to encrypt/decrypt files

mjames picture mjames · Jun 23, 2011 · Viewed 13.6k times · Source

I need to transfer xml files and they are required to be encrypted. I have found some examples think I'm close but when I decrypt the file I end up with trailing junk characters. There are some posts about this but I have not seen any that will exactly help. Here is the encrypt and decrypt code.

private void EncryptFile(string inputFile, string outputFile, string key) {
    try {
        byte[] keyBytes;
        keyBytes = Encoding.Unicode.GetBytes(key);

        Rfc2898DeriveBytes derivedKey = new Rfc2898DeriveBytes(key, keyBytes);

        RijndaelManaged rijndaelCSP = new RijndaelManaged();
        rijndaelCSP.Key = derivedKey.GetBytes(rijndaelCSP.KeySize / 8);
        rijndaelCSP.IV = derivedKey.GetBytes(rijndaelCSP.BlockSize / 8);

        ICryptoTransform encryptor = rijndaelCSP.CreateEncryptor();

        FileStream inputFileStream = new FileStream(inputFile, FileMode.Open, FileAccess.Read);

        byte[] inputFileData = new byte[(int)inputFileStream.Length];
        inputFileStream.Read(inputFileData, 0, (int)inputFileStream.Length);

        FileStream outputFileStream = new FileStream(outputFile, FileMode.Create, FileAccess.Write);

        CryptoStream encryptStream = new CryptoStream(outputFileStream, encryptor, CryptoStreamMode.Write);
        encryptStream.Write(inputFileData, 0, (int)inputFileStream.Length);
        encryptStream.FlushFinalBlock();

        rijndaelCSP.Clear();
        encryptStream.Close();
        inputFileStream.Close();
        outputFileStream.Close();
    }
    catch (Exception ex) {
        MessageBox.Show(ex.Message, "Encryption Failed!", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return;
    }

    MessageBox.Show("File Encryption Complete!");

}

private void DecryptFile(string inputFile, string outputFile, string key) {
    try {
        byte[] keyBytes = Encoding.Unicode.GetBytes(key);

        Rfc2898DeriveBytes derivedKey = new Rfc2898DeriveBytes(key, keyBytes);

        RijndaelManaged rijndaelCSP = new RijndaelManaged();
        rijndaelCSP.Key = derivedKey.GetBytes(rijndaelCSP.KeySize / 8);
        rijndaelCSP.IV = derivedKey.GetBytes(rijndaelCSP.BlockSize / 8);
        ICryptoTransform decryptor = rijndaelCSP.CreateDecryptor();

        FileStream inputFileStream = new FileStream(inputFile, FileMode.Open, FileAccess.Read);

        CryptoStream decryptStream = new CryptoStream(inputFileStream, decryptor, CryptoStreamMode.Read);

        byte[] inputFileData = new byte[(int)inputFileStream.Length];
        decryptStream.Read(inputFileData, 0, (int)inputFileStream.Length);

        FileStream outputFileStream = new FileStream(outputFile, FileMode.Create, FileAccess.Write);
        outputFileStream.Write(inputFileData, 0, inputFileData.Length);
        outputFileStream.Flush();

        rijndaelCSP.Clear();

        decryptStream.Close();
        inputFileStream.Close();
        outputFileStream.Close();
    }
    catch (Exception ex) {
        MessageBox.Show(ex.Message, "Decryption Failed!", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return;
    }

    MessageBox.Show("File Decryption Complete!");
}

I end up with

<?xml version="1.0" encoding="UTF-8"?>
<transaction>
  <header>
    <qOrderNumber></qOrderNumber>
    <qRequestDate></qRequestDate>
    <testOrder></testOrder>
    <qCustomerNumber></qCustomerNumber>
    <transactionStatus></transactionStatus>
  </header>
  <lines>
    <line>
      <productID></productID>
      <serialNumber></serialNumber>
    </line>
    <line> 
      <productID></productID>
      <serialNumber></serialNumber>
    </line>
  </lines>
</transaction>NULNULNULNULNULNUL

Answer

The Moof picture The Moof · Jun 23, 2011

When decrypting, pay attention to the return value from the CryptoStream.Read call. It tells you the length of the decrypted data in your byte array (usually will not match the length of the encrypted data due to padding). Try using the following in your decrypt function:

int decrypt_length = decryptStream.Read(inputFileData, 0, (int)inputFileStream.Length);
FileStream outputFileStream = new FileStream(outputFile, FileMode.Create, FileAccess.Write);
outputFileStream.Write(inputFileData, 0, decrypt_length);