使用 C# AES 或 Rijndael 加密和解密 xlsx、docx 文件

发布于 2024-11-23 20:28:13 字数 3077 浏览 1 评论 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;
}

We encrypt all types of files using Rijndael encryption. Newer .xlsx and .docx files are throwing errors when trying to open (after encrypting and trying to decrypt). Error when Excel 2003 tries to open file: "The converter failed to open the file". I have Excel add on installed and when not using encryption/decryption I am able to open xlsx files in Excel 2003.

I have changed out the code to use AES, with same type of issue (but in this case the file will not download, just sits there in the Firefox download list). I've read suggestions here to pay attention to byte size/lengths of encrypted/decrypted files but am at a loss as to how to fix this, I see that if I upload a xls file the length of the encrypted file going in is different from the decrypted file coming out and xls save and open fine, so I don't know how to test if this is the issue since these lenghts differ on files that do work. I am including the code to see if anyone can spot any issues that could be contributing to xlsx/docx file encryption errors. I've minimized the code, so if any syntax errors, is probably due to that.

I have installed Excel 2007 to see if the .xlsx files that are encrypted and decrypted will open in Excel 2007. When I attempt to open the file, I get a prompt:"Excel found unreadable content in 'myfile.xlsx'. Do you want to recover the contents of this workbook?". Excel 2007 is able to recover/repair the file with message: "Excel completed the file level validation and repair. Some parts of this workbook may have been repaired or discarded". So, the encryption/decryption creates invalid file but Excel 2007 is able to repair this; Excel 2003 converter cannot do anything with the file.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

春夜浅 2024-11-30 20:28:13

如果您担心填充,这里有一些适合您的内容:

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

If the padding is of concern, here is something for you:

How do I encrypt a string in vb.net using RijndaelManaged, and using PKCS5 padding?

痴骨ら 2024-11-30 20:28:13

听起来像是一个截断问题;可能是因为您创建内存流的方式;当我解密时,它看起来如下所示,

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

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

Sounds like a truncation issue; possibly because of the way you're creating the memory stream; when I decrypt it looks like the following

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

I'd guess that there are extra null bytes being appended, and using the alternate approach may alleviate this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文