加密文件c#时减少内存消耗

时间:2014-08-20 11:57:10

标签: c# file memory encryption aes

我的加密应用程序正在使用大量内存,它根本无法处理大文件,如何优化处理大文件的代码?我使用下面的代码将文件转换为base64(显着增加文件大小)

Console.Write("Enter File Path: ");
docPath = Console.ReadLine();
extension = docPath.Substring(docPath.IndexOf(".")).Trim();
byte[] binarydata = File.ReadAllBytes(docPath);
text = System.Convert.ToBase64String(binarydata, 0, binarydata.Length);
var Encrypted = AESCryptography.Encrypt(text, m.ToString(), extension);
using (FileStream fs = File.Create(docPath.Substring(0,docPath.IndexOf(".")) + ".aent"))
{
    Byte[] info = new UTF8Encoding(true).GetBytes(Encrypted);
    // Add some information to the file.
    fs.Write(info, 0, info.Length);
}

我怎么能在街区做到这一点?继承我的加密类:

public static class AESCryptography
{
    private const int keysize = 256;
    public static string Encrypt(string plainText, string passPhrase, string extention)
    {
        byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
        using (PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null))
        {
            byte[] keyBytes = password.GetBytes(keysize / 8);
            using (RijndaelManaged symmetricKey = new RijndaelManaged())
            {
                symmetricKey.GenerateIV();
                symmetricKey.Mode = CipherMode.CBC;
                using (ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, symmetricKey.IV))
                {
                    using (MemoryStream memoryStream = new MemoryStream())
                    {
                        using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                        {
                            cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
                            cryptoStream.FlushFinalBlock();
                            byte[] cipherTextBytes = memoryStream.ToArray();
                            return Convert.ToBase64String(cipherTextBytes) + "\n" + Convert.ToBase64String(symmetricKey.IV) + "\n" + extention;
                        }
                    }
                }
            }
        }
    }

    public static string Decrypt(string cipherText, string passPhrase, string initVector)
    {
        byte[] initVectorBytes = Convert.FromBase64String(initVector);
        byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
        using (PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null))
        {
            byte[] keyBytes = password.GetBytes(keysize / 8);
            using (RijndaelManaged symmetricKey = new RijndaelManaged())
            {
                symmetricKey.Mode = CipherMode.CBC;
                using (ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes))
                {
                    using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes))
                    {
                        using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
                        {
                            byte[] plainTextBytes = new byte[cipherTextBytes.Length];
                            int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
                            return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
                        }
                    }
                }
            }
        }
    }
}

2 个答案:

答案 0 :(得分:2)

  • 首先,您要从文件中读取字节:byte[] binarydata = File.ReadAllBytes(docPath);
  • 然后您将字节转换为字符串:text = System.Convert.ToBase64String(binarydata, 0, binarydata.Length);
  • 然后你从字符串中获取字节:byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);

您当前正在内存中存储所有大文件两次(实际上是两倍以上,因为base64字符串使用的内存多于字节数组)。

解决方案:

  • 删除转换为/来自字符串的部分,这样就不会使用字符串,只能使用字节。
  • 然后删除整个ReadAllBytes的东西,将所有文件加载到内存中,然后用小块处理。例如,请参阅Using Rijndael encryption for large files

答案 1 :(得分:1)

  • 请勿将IV存储在文件的 end 中。您正在强制读者首先阅读整个加密文件,以发现需要顶部读取文件的IV。将其存储在文件的开头。

  • 不要对文件base64进行编码。 Base64是一种传输格式,而不是存储格式。

  • 使用Stream.CopyTo读取文件并写入CryptoStream,无需一次读取内存中的所有内容。按目标文件流返回CryptoStream,而不是通过内存流。

  • Ditto for decryption,读取CryptoStream(在跳过IV后由输入流支持)和CopyTo目标文件流