使用 Rijndael 加密/解密文件
我需要传输 xml 文件,并且需要对它们进行加密。我发现一些例子认为我已经接近了,但是当我解密文件时,我最终得到了尾随垃圾字符。有一些关于此的帖子,但我还没有看到任何能真正有帮助的帖子。这是加密和解密代码。
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!");
}
我最终得到
<?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
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
解密时,请注意 CryptoStream.Read 调用的返回值。它告诉您字节数组中解密数据的长度(通常由于填充而与加密数据的长度不匹配)。尝试在解密函数中使用以下内容:
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:
在
RijndaelManaged
对象上,将Padding
属性设置为PaddingMode.ANSIX923
或PaddingMode.ISO10126
。添加这些空字节来填充最终的加密块。默认情况下用零填充,这意味着没有给出数据的实际长度。其他填充模式在最后一个字节中包含长度,以便在解密后可以删除填充。
将加密和解密例程中的填充属性设置为相同的值。
如果它知道会发生什么,那么解密流将自动删除填充,因此不需要进一步的更改。
更新
从您的代码来看,您写入输出文件的字节数似乎等于从输入文件读取的字节数。
由于输入中存在填充,解密过程不会完全填满
inputFileData
数组。然后,输出流将写出缓冲区的整个长度,即使缓冲区没有完全填满。
这是你的空值的来源。
您可能想要更改加密和解密的方式,以便它不再使用固定长度的缓冲区。或者,您可以在开头存储加密数据的长度,并只写入与该长度相对应的字节数。
On the
RijndaelManaged
object, set thePadding
property toPaddingMode.ANSIX923
orPaddingMode.ISO10126
.Those null bytes were added to fill out the final encrypted block. It was padded with zeros by default, which means that no indication is given as to the actual length of the data. The other padding modes include a length in the final byte, so that the padding can be removed after decryption.
Set the padding property in both the encrypt and decrypt routine to the same value.
If it knows what to expect, then the decryption stream will remove the padding automatically, so no further changes should be necessary.
UPDATE
From looking at your code, it appears that the number of bytes that you are writing to the output file is equal to the number of bytes read in from the input file.
The decryption process is not going to completely fill up the
inputFileData
array, because of the padding in the input.The output stream will then write out the entire length of the buffer, even though it wasn't completely filled.
This is the source of your nulls.
You may want to change the way you are doing the encryption and decryption so that it no longer uses fixed-length bufferes. Alternatively, you could store the length of the encrypted data at the beginning, and only write the number of bytes that correspond to that length.