我们使用 Rijndael 加密对所有类型的文件进行加密。较新的 .xlsx 和 .docx 文件在尝试打开时(在加密和尝试解密之后)会引发错误。Excel 2003 尝试打开文件时出错:“转换器无法打开文件”。我安装了 Excel 插件,当不使用加密/解密时,我可以在 Excel 2003 中打开 xlsx 文件。
我已将代码更改为使用 AES,但存在相同类型的问题(但在这种情况下,文件不会下载,只是位于 Firefox 下载列表中)。我在这里阅读了有关注意加密/解密文件的字节大小/长度的建议,但不知道如何解决这个问题,我发现如果我上传 xls 文件,进入的加密文件的长度是不同的从解密的文件出来,xls保存并打开正常,所以我不知道如何测试这是否是问题,因为这些长度在有效的文件上有所不同。我包含代码以查看是否有人能发现任何可能导致 xlsx/docx 文件加密错误的问题。我已经最小化了代码,所以如果有任何语法错误,可能是由于这个原因。
我已经安装了 Excel 2007 来查看加密和解密的 .xlsx 文件是否会在 Excel 2007 中打开。当我尝试打开文件时,我得到一个提示:“Excel 在 'myfile.xlsx' 中发现了不可读的内容。你要恢复此工作簿的内容吗?”。Excel 2007 能够通过以下消息恢复/修复文件:“Excel 完成了文件级别的验证和修复。此工作簿的某些部分可能已被修复或丢弃”。因此,加密/解密会创建无效文件,但 Excel 2007 能够修复此问题;Excel 2003 转换器无法对该文件执行任何操作。
public byte [] Encrypt(byte [] bytes)
{
if (myRijndael == null)
myRijndael = new RijndaelManaged();
ICryptoTransform encryptor = myRijndael.CreateEncryptor(key, IV);
MemoryStream msEncrypt = new MemoryStream();
CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
csEncrypt.Write(bytes, 0, bytes.Length);
csEncrypt.FlushFinalBlock();
return msEncrypt.ToArray();
}
public byte [] Decrypt(byte [] encrypted, string text)
{
if (myRijndael == null)
{
myRijndael = new RijndaelManaged();
}
ICryptoTransform decryptor = myRijndael.CreateDecryptor(key, IV);
MemoryStream msDecrypt = new MemoryStream(encrypted);
CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
byte [] fromEncrypt = new byte[encrypted.Length];
csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
return fromEncrypt;
}
Usage:
ENCRYPT:
ClcCrypto crypt; // Our class for saving keys etc.
ClcCrypto(CLC.WebUtil.ClcCrypto.GetDecryptionKey(), Group.IV);
BinaryReader br = new BinaryReader(NewFile);// NewFile is Stream from filMyFile.PostedFile.InputStream
byte[] EncryptedContents = crypt.Encrypt(br.ReadBytes((int)NewFile.Length));
FileStream fs = File.Create(DestFileName);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(EncryptedContents);
bw.Close();
fs.Close();
br.Close();
DECRYPT (file download):
byte[] baOut = null;
baOut = fiOut.GetFileData(out lLength); // See below for method
Response.AddHeader("content-disposition", "attachment; filename=" + FileName));
Response.ContentType = fiOut.MimeType;
Response.AddHeader("content-length", lLength.ToString());
Response.BinaryWrite(baOut);
Response.End();
public byte[] GetFileData(out long intFileSize)
{
FileStream fsOut = new FileStream(FilePath, FileMode.Open, FileAccess.Read);
intFileSize = fsOut.Length;
byte[] Buffer = null;
ClcCrypto crypt;
crypt = new CLC.WebUtil.ClcCrypto(CLC.WebUtil.ClcCrypto.GetDecryptionKey(), IV);
BinaryReader br = new BinaryReader(fsOut);
Buffer = crypt.Decrypt(br.ReadBytes((int)fsOut.Length), null);
br.Close();
fsOut.Close();
return Buffer;
}