且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-08-20 11:25:58


  • 首先,您正在从文件中读取字节: byte [] binaryData = File.ReadAllBytes(docPath);

  • 然后将字节转换为字符串: text = System.Convert.ToBase64String (binarydata,0,binarydata.Length);

  • 然后你从字符串中取回你的字节: byte [] plainTextBytes = Encoding.UTF8.GetBytes(plainText);



您正在内存中存储所有的



解决方案:




  • 删除转换为/从字符串的部分,所以不要使用字符串,只能使用字节。

  • 然后放下整个ReadAll字节的东西,加载所有的文件在内存中,并通过小块进行处理。请参阅对大文件使用Rijndael加密,例如


My encryption app is using to much memory and it simply can't handle large files, how can I optimize my code for handling large files? I am using the code below to convert the file to base64 (increasing the file size dramatically)

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

How can I do this in blocks? Heres my encryption class:

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

  • First you're reading bytes from your file: byte[] binarydata = File.ReadAllBytes(docPath);
  • Then you're converting bytes to a string: text = System.Convert.ToBase64String(binarydata, 0, binarydata.Length);
  • Then you're getting your bytes back from the string: byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);

You're currently storing in memory all of your large file twice (actually way more than twice because base64 string uses more memory than just a byte array).

Solution:

  • Drop the part that converts to/from string so you don't use strings at all but only bytes.
  • Then drop the whole ReadAllBytes thing that loads all your file in memory and process by small chunks instead. See Using Rijndael encryption for large files for example