henk
henk

Reputation: 13

Memory issue while encrypting files

I have a memory issue while reading a file and encrypt it in C# UWP.

This is my code:

using System;
using System.Text;
using System.IO;
using System.Security.Cryptography;
using Windows.Storage;
using System.Runtime.InteropServices.WindowsRuntime;

public async void encrypt_file(StorageFile file, string key, string pw_salt)
    {
        try
        {
            SymmetricAlgorithm algorithm = Aes.Create();

            DeriveBytes rgb = new Rfc2898DeriveBytes(key, Encoding.Unicode.GetBytes(pw_salt));//create password
            byte[] rgbKey = rgb.GetBytes(algorithm.KeySize >> 3);
            byte[] rgbIV = rgb.GetBytes(algorithm.BlockSize >> 3);

            ICryptoTransform transform = algorithm.CreateEncryptor(rgbKey, rgbIV);//create encrytor/decryptor

            using (MemoryStream memStream = new MemoryStream())
            {
                using (CryptoStream cryptoStream = new CryptoStream(memStream, transform, CryptoStreamMode.Write))
                {
                    byte[] plainContent = (await FileIO.ReadBufferAsync(file)).ToArray();//read bytes
                     cryptoStream.Write(plainContent, 0, plainContent.Length);
                     cryptoStream.FlushFinalBlock();
                    await FileIO.WriteBufferAsync(file, memStream.ToArray().AsBuffer());//write bytes
                    await file.RenameAsync(file.Name + ".myfile");

                    plainContent = null;
                    cryptoStream.Dispose();
                    memStream.Dispose();
                    transform.Dispose();
                }
            }
            GC.Collect();
        }
        catch { }
    }

After I run this code, my application is using too much memory. What am I doing wrong?

Upvotes: 0

Views: 96

Answers (1)

ckuri
ckuri

Reputation: 4535

Posted as an answer, because as a comment it would be illegible.

I don't have experience with UWP, so unfortunately I can't make the exact changes to your code, but in general .NET you would do:

    var buffer = new byte[1024 * 1024]; // 1MB buffer
    using (var encryptedStream = new FileStream("FileName.ext.aes", FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, buffer.Length, FileOptions.Asynchronous))
    {
      using (var crypto = new CryptoStream(encryptedStream, encryptor, CryptoStreamMode.Write))
      {
        using (var unencryptedStream = new FileStream("FileName.ext", FileMode.Open, FileAccess.Read, FileShare.Read, buffer.Length, FileOptions.Asynchronous))
        {
          int bytesRead;
          do
          {
            bytesRead = await unencryptedStream.ReadAsync(buffer, 0, buffer.Length);
            await crypto.WriteAsync(buffer, 0, bytesRead);
          } while (bytesRead == buffer.Length);
        }
      }
    }

So, you read a block from your unencrypted stream and write it to your crypro stream, who in turn will encrypt the data and writes this to your output stream. Then you check if the amount of data read equals the requested amount of data to be read (buffer.Length). If its less it means you reached the end of the stream.

This way your memory footprint is restricted to the buffer size (in this example 1MB).

Upvotes: 3

Related Questions