首页 > 解决方案 > 如何使用 AES 加密文本文件以外的文件?PDF、Word 等

问题描述

我正在尝试在 C# ASP NET 5.0 中加密/解密文件,当然我可以让它适用于 .txt 文件和常规字符串。但是,如果我尝试加密 PDF 文件然后解密它,它已损坏并且我无法打开它。我现在只是在使用 EBC,我知道它不安全,但我只是想在添加其他选项之前对其进行测试。

    public static void encrypt(string fileLocation, string encryptedFileLocation, string key)
        {
            FileStream fp = new FileStream(fileLocation, FileMode.Open, FileAccess.Read);
            FileStream encryptedFile = new FileStream(encryptedFileLocation, FileMode.Create);

            using (Aes aes = Aes.Create())
            {
                aes.Key = Encoding.UTF8.GetBytes(key);
                aes.Mode = CipherMode.ECB;
                aes.Padding = PaddingMode.PKCS7;

                ICryptoTransform encryptor = aes.CreateEncryptor(Encoding.UTF8.GetBytes("asdfasdfasdfasdf"), Encoding.UTF8.GetBytes("fdsafdsafdsafdsa"));
                CryptoStream cryptoStream = new CryptoStream(encryptedFile, encryptor, CryptoStreamMode.Write);

                byte[] buffer = new byte[1024];
                int read;

                try
                {
                    while((read = fp.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        cryptoStream.Write(buffer, 0, read);
                        cryptoStream.FlushFinalBlock();
                    }
                } 
                catch(Exception e)
                {

                }
                finally
                {
                    fp.Close();
                    encryptedFile.Close();
                }

            }
        }

        public static void decrypt(string cypherFileLocation, string decryptedFileLocation, string key)
        {
            FileStream fp = new FileStream(cypherFileLocation, FileMode.Open, FileAccess.Read);
            FileStream decryptedFile = new FileStream(decryptedFileLocation, FileMode.Create);


            using (Aes aes = Aes.Create())
            {
                aes.Key = Encoding.UTF8.GetBytes(key);
                aes.Mode = CipherMode.ECB;
                aes.Padding = PaddingMode.PKCS7;

                ICryptoTransform decryptor = aes.CreateDecryptor(Encoding.UTF8.GetBytes("asdfasdfasdfasdf"), Encoding.UTF8.GetBytes("fdsafdsafdsafdsa"));
                CryptoStream cryptoStream = new CryptoStream(fp, decryptor, CryptoStreamMode.Read);

                try
                {
                    byte[] buffer = new byte[1024];
                    int read;
                    while((read = cryptoStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        decryptedFile.Write(buffer, 0, read);
                        decryptedFile.Flush();
                    }
                }
                catch(Exception e)
                {

                }
                finally
                {
                    fp.Close();
                    decryptedFile.Close();
                }
            }
        }

标签: c#asp.netencryptionaes

解决方案


正如我在上面的评论中所述,您的代码中有一个不可见的错误,因为您使用空的 catch 块隐藏了异常。异常是 NotSupportedException 并且消息是

FlushFinalBlock() 方法在 CryptoStream 上被调用了两次。只能调用一次

加密适用于长度小于 1024 字节的文本文件,但任何较大的文件(也是文本文件)都会崩溃,因为代码尝试调用两次或更多次cryptoStream.FlushFinalBlock();

因此,我已经对您的代码进行了测试,并且可以正常工作

try
{
    while ((read = fp.Read(buffer, 0, buffer.Length)) > 0)
    {
        cryptoStream.Write(buffer, 0, read);
    }
    // Moved outside the loop
    cryptoStream.FlushFinalBlock();
}
catch (Exception e)
{
    Console.WriteLine(e.Message);
}
finally
{
    fp.Close();
    encryptedFile.Close();
}

在解密例程中,您还可以在循环内调用 Flush ,这不是必需的,可以移到循环外。但在这种情况下,没有可见的错误。无论如何,不​​要隐藏异常,它们对于理解和修复错误至关重要。


推荐阅读