0

I try to read a file, separate the lines (each line represents different data), decrypt the symmetric key with my RSA private key, decrypt and verify the data using AES GCM, and write it to the same directory.

But after decrypting the data it looks like it still holds a lot of RAM.

before decrypting a large file

after decrypting a 700MB file

I tried to use the .clear function, assigning the variable to null, and using the GC.Collect() function.

The GC.Collect() worked the best (reduced RAM usage from 6GB to 1.5GB when decrypting 700MB file).

Here is the the function that runs when I try to decrypt.

private void decrypt()
    {
        if (!decrypted)
        {
            try
            {
                string[] lines = File.ReadAllLines(openFileDialog1.FileName);
                byte[] encryptedsk = Convert.FromBase64String(lines[0]);
                byte[] nonce = Convert.FromBase64String(lines[1]);
                byte[] tag = Convert.FromBase64String(lines[2]);
                byte[] cipherText = Convert.FromBase64String(lines[3]);
                Array.Clear(lines, 0, lines.Length);
                lines = null;
                GC.Collect();
                var privkey = File.ReadAllText(openFileDialog2.FileName);
                var key = RSA.Create();
                key.ImportFromPem(privkey);
                privkey = null;
                byte[] secretkey;
                RSAEncryptionPadding padd = RSAEncryptionPadding.OaepSHA1;
                secretkey = key.Decrypt(encryptedsk, padd);
                key = null;
                GC.Collect();
                using (var cipher = new AesGcm(secretkey))
                {
                    byte[] decryptedData = new byte[cipherText.Length];
                    cipher.Decrypt(nonce, cipherText, tag, decryptedData);
                    Array.Clear(nonce, 0, nonce.Length);
                    Array.Clear(secretkey, 0, secretkey.Length);
                    Array.Clear(cipherText, 0, cipherText.Length);
                    nonce = null;
                    secretkey = null;
                    cipherText = null;
                    File.WriteAllBytesAsync(openFileDialog1.FileName + ".cfg", decryptedData);
                    Array.Clear(decryptedData, 0, decryptedData.Length);
                    decryptedData = null;
                    label1.Text = string.Format("successfuly decrypted to\n{0}.cfg", openFileDialog1.FileName);
                }

                decrypted = true;

            }
            catch
            {
                label1.Text = "One of the files isn't correct";
                GC.Collect();
            }
        }
        GC.Collect();
    }

Would love to know where I failed.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
macie
  • 33
  • 5
  • Since you are using File.WriteAllBytesAsync could it be that the writing is not over ? – Pierre Michel Jan 23 '21 at 12:58
  • I don't think so. I used before File.WriteAllBytes and it had the same result, also the file works correctly and has the same hash. – macie Jan 23 '21 at 13:02
  • Have you tried that: GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); – Pierre Michel Jan 23 '21 at 13:10
  • Added it everywhere in my function and put it after the function and it reduced the RAM usage to 50 MB RAM after the decryption. Thanks a lot! Do you maybe know why it still takes 24 MB more after the function? – macie Jan 23 '21 at 13:19
  • this happens due to the way garbage collection works, if you waited for some time the memory would be released anyway. – NullReference Jan 23 '21 at 14:36
  • Yes by the way, calling GC so much takes a lot of time I think so better just do it once at the end. As NullReference said it would be freed anyway after some time – Pierre Michel Jan 23 '21 at 16:39
  • 3
    You're probably best running this in streaming mode, so you're not holding the whole file in memory all at once – Charlieface Jan 23 '21 at 18:55
  • Yeah, second that, you don't need to clear the RAM if you don't use it in the first place. – Maarten Bodewes Jan 23 '21 at 20:37
  • I couldn't find a way to use stream with AES GCM unfortunately, could you perhaps direct me in the correct direction? the Microsoft docs didn't help me in this case. – macie Jan 23 '21 at 21:51

0 Answers0