0

我们使用 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;
}
4

2 回答 2

0

如果填充是令人担忧的,这里有一些适合你的东西:

如何使用 RijndaelManaged 和 PKCS5 填充加密 vb.net 中的字符串?

于 2011-07-12T23:39:54.950 回答
0

听起来像是截断问题;可能是因为您创建内存流的方式;当我解密它看起来像下面

MemoryStream msDecrypt = new MemoryStream();
CryptoStream csDecrypt = new CryptoStream(
    msDecrypt, 
    decryptor, 
    CryptoStreamMode.Write);
csStream.Write(encrypted, 0, encrypted.Length);
csStream.Flush();
return csDecrypt.ToArray();

我猜想附加了额外的空字节,使用替代方法可能会缓解这种情况。

于 2011-07-13T18:19:29.730 回答