我需要传输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
答案 0 :(得分:10)
解密时,请注意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);
答案 1 :(得分:2)
在RijndaelManaged
对象上,将Padding
属性设置为PaddingMode.ANSIX923
或PaddingMode.ISO10126
。
添加了那些空字节以填写最终的加密块。默认情况下,它用零填充,这意味着没有给出关于数据实际长度的指示。其他填充模式包括最后一个字节的长度,以便在解密后删除填充。
将encrypt和decrypt例程中的padding属性设置为相同的值。
rijndaelCSP.Padding = PaddingMode.ANSIX923;
如果它知道会发生什么,那么解密流将自动删除填充,因此不需要进一步更改。
<强>更新强>
从查看代码看,您写入输出文件的字节数似乎等于从输入文件读入的字节数。
byte[] inputFileData = new byte[(int)inputFileStream.Length];
decryptStream.Read(inputFileData, 0, (int)inputFileStream.Length);
由于输入中的填充,解密过程不会完全填满inputFileData
数组。
输出流将写出缓冲区的整个长度,即使它没有完全填满。
outputFileStream.Write(inputFileData, 0, inputFileData.Length);
这是空值的来源。
您可能希望更改加密和解密的方式,以便它不再使用固定长度的bufferes。或者,您可以在开头存储加密数据的长度,并且只写入与该长度对应的字节数。