使用Rijndael加密/解密文件

我需要传输xml文件,并且需要加密它们。 我发现一些例子认为我很接近,但是当我解密文件时,我最终得到了尾随垃圾字符。 有一些关于这个的post,但我没有看到任何将完全有帮助。 这是加密和解密代码。

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!"); } 

我结束了

   
NULNULNULNULNULNUL

解密时,请注意CryptoStream.Read调用的返回值。 它告诉您字节数组中解密数据的长度(通常不会因填充而与加密数据的长度相匹配)。 尝试在解密函数中使用以下内容:

 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); 

RijndaelManaged对象上,将Padding属性设置为PaddingMode.ANSIX923PaddingMode.ISO10126

添加了那些空字节以填充最终的加密块。 默认情况下,它用零填充,这意味着没有给出关于数据实际长度的指示。 其他填充模式包括最后字节中的长度,以便在解密后可以移除填充。

将encrypt和decrypt例程中的padding属性设置为相同的值。

  rijndaelCSP.Padding = PaddingMode.ANSIX923; 

如果它知道会发生什么,那么解密流将自动删除填充,因此不需要进一步的更改。

UPDATE

从查看代码看,您写入输出文件的字节数似乎等于从输入文件读入的字节数。

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

由于输入中的填充,解密过程不会完全填满inputFileData数组。

然后输出流将写出缓冲区的整个长度,即使它没有完全填充。

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

这是空值的来源。

您可能希望更改加密和解密的方式,以便它不再使用固定长度的bufferes。 或者,您可以在开头存储加密数据的长度,并仅写入与该长度对应的字节数。