Using Rijndael to Encrypt / Decrypt Files

I need to transfer xml files and they must be encrypted. I found some examples, I think I'm close, but when I decrypt the file, I get trailing garbage characters. There are a few posts about this, but I have not seen one that will definitely help. Here is the encryption and decryption 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!"); } 

The end result

 <?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 
+6
source share
2 answers

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

 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); 
+10
source

In the RijndaelManaged object, set the Padding property to PaddingMode.ANSIX923 or PaddingMode.ISO10126 .

These null bytes were added to fill the final encrypted block. By default, it was filled with zeros, which means that the actual data length is not indicated. Other padding modes include length in the last byte, so indentation can be removed after decryption.

Set the padding property in both the encrypted and decrypted routine with the same value.

  rijndaelCSP.Padding = PaddingMode.ANSIX923; 

If he knows what to expect, then the decryption stream will automatically delete the filling, so no further changes will be required.

UPDATE

Looking at your code, it seems that the number of bytes you write to the output file is equal to the number of bytes read from the input file.

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

The decryption process will not completely fill the inputFileData array due to the input filling.

Then the output stream writes out the entire length of the buffer, although it was not completely full.

 outputFileStream.Write(inputFileData, 0, inputFileData.Length); 

This is the source of your zeros.

You might want to change the encryption and decryption method so that it no longer uses fixed-length buffers. In addition, you can save the length of the encrypted data at the beginning and record the number of bytes corresponding to this length.

+2
source

Source: https://habr.com/ru/post/891249/


All Articles