简体   繁体   English

AES 加密文件超过 1GB

[英]AES encryption on file over 1GB

I am making a app that will encrypt 5 video files.我正在制作一个可以加密 5 个视频文件的应用程序。 The problem is that it only encrypts 4 out of 5 files(the ones <1gb).问题是它只加密了 5 个文件中的 4 个(<1gb)。 On the 5th file, which is over 1GB, the System.OutOfMemoryException is thrown.在超过 1GB 的第 5 个文件上,抛出 System.OutOfMemoryException。 (i know i asked it previously ,but i made some changes as suggested but it still wont work, i dont mean to spam) Here's my code: (我知道我之前问过它,但我按照建议做了一些更改但它仍然不起作用,我不是要发送垃圾邮件)这是我的代码:

//Encrypts single file
public void EncryptFile(string file, string password)
{
    byte[] bytesToBeEncrypted = File.ReadAllBytes(file);
    byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
    // Hash the password with SHA256
    passwordBytes = SHA256.Create().ComputeHash(passwordBytes);

    byte[] salt = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
    FileStream fsCrypt = new FileStream(file + ".enc", FileMode.Create);

    //Set Rijndael symmetric encryption algorithm
    RijndaelManaged AES = new RijndaelManaged();
    AES.KeySize = AES.LegalKeySizes[0].MaxSize;
    AES.BlockSize = AES.LegalBlockSizes[0].MaxSize;
    AES.Padding = PaddingMode.PKCS7;

    //"What it does is repeatedly hash the user password along with the salt." High iteration counts.
   var key = new Rfc2898DeriveBytes(passwordBytes, salt, 1000);
   AES.Key = key.GetBytes(AES.KeySize / 8);
   AES.IV = key.GetBytes(AES.BlockSize / 8);
   AES.Mode = CipherMode.CFB;

   //write salt to the beginning of the output file, so in this case can be random every time
   fsCrypt.Write(salt, 0, salt.Length);

   CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateEncryptor(), CryptoStreamMode.Write);
   FileStream fsIn = new FileStream(file, FileMode.Open);

   //create a buffer (1mb) so only this amount will allocate in the memory and not the whole file
   byte[] buffer = new byte[5048576];
   int read;

   try
   {
       while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)
       {
           Application.DoEvents();
           cs.Write(buffer, 0, read);
       }

       fsIn.Close();
       fsIn.Dispose();
    }
    catch (System.OutOfMemoryException ex)
    {
        cs.Flush();
        cs.Dispose();
    }
    finally
    {
        cs.Close();
        fsCrypt.Close();
    }

You are reading the entire file at the start of the method:您正在方法开始时读取整个文件:

byte[] bytesToBeEncrypted = File.ReadAllBytes(file); 

This is causing the OutOfMemoryException.这会导致 OutOfMemoryException。 Here's an idea of how you'd do this:这是您如何执行此操作的想法

static void EncryptFile(string file, string password)
{
    byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
    byte[] salt = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

    passwordBytes = SHA256.Create().ComputeHash(passwordBytes);

    RijndaelManaged AES = new RijndaelManaged();
    AES.KeySize = AES.LegalKeySizes[0].MaxSize;
    AES.BlockSize = AES.LegalBlockSizes[0].MaxSize;
    AES.Padding = PaddingMode.PKCS7;

    //"What it does is repeatedly hash the user password along with the salt." High iteration counts.
    using (var key = new Rfc2898DeriveBytes(passwordBytes, salt, 1000)) // automatically dispose key
    {
        AES.Key = key.GetBytes(AES.KeySize / 8);
        AES.IV = key.GetBytes(AES.BlockSize / 8);
        AES.Mode = CipherMode.CFB;
    }
    using (FileStream fsCrypt = new FileStream(file + ".enc", FileMode.Create)) // automatically dispose fsCrypt
    {
        //write salt to the beginning of the output file, so in this case can be random every time
        fsCrypt.Write(salt, 0, salt.Length);
    }

    int bytesToRead = 128 * 1024 * 1024; // 128MB 
    byte[] buffer = new byte[bytesToRead]; // create the array that will be used encrypted
    long fileOffset = 0;
    int read = 0;
    bool allRead = false;

    while (!allRead)
    {
       using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
       {
           fs.Seek(fileOffset, SeekOrigin.Begin); // continue reading from where we were...
           read = fs.Read(buffer, 0, bytesToRead); // read the next chunk
       }

       if (read == 0)
           allRead = true;
       else
           fileOffset += read;

       using (FileStream fsCrypt = new FileStream(file + ".enc", FileMode.Open)) // automatically dispose fsCrypt
       {
           using (CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateEncryptor(), CryptoStreamMode.Write))
           {
               fsCrypt.Seek(fileOffset, SeekOrigin.End);
               cs.Write(buffer, 0, read);
           }
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM