Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory leak in .NET when using the native crypto providers

I have an application which needs to encrypt and decrypt strings. Below is my decryption method:

  public static string Decrypt(string cipherText)
  {
     try
     {
        //Decrypt:
        byte[] keyArray;
        byte[] toDecryptArray = Convert.FromBase64String(cipherText);
        keyArray = UTF8Encoding.UTF8.GetBytes(key);
        AesCryptoServiceProvider Aes = new AesCryptoServiceProvider();
        Aes.Key = keyArray;
        Aes.Mode = CipherMode.CBC;
        Aes.Padding = PaddingMode.PKCS7;
        Aes.IV = IV;
        ICryptoTransform cTransform = Aes.CreateDecryptor();
        byte[] resultArray = cTransform.TransformFinalBlock(toDecryptArray, 0, toDecryptArray.Length);
        Aes.Clear();
        return UTF8Encoding.UTF8.GetString(resultArray, 0, resultArray.Length);
     }
     catch (Exception ex)
     {
        return "FAILED:*" + cipherText + "*" + ex.Message;
     }
  }

However, this seems to leak. As you can see, all of the variables are scoped locally so they should be released when this block is done. As background, I'm calling this method sometimes almost nonstop.

In order to determine that there was I leak I inundate my server with many requests. By carefully tracing each request through each path of code it takes, I determined this piece of code is the culprit. When commented in my memory use goes up drastically and linearly, when commented out (and simply returning the cipherText) memory use stays even.

like image 788
kmarks2 Avatar asked Nov 28 '22 07:11

kmarks2


1 Answers

AesCryptoServiceProvider implements IDisposable. Try to use it in a using-block. Something like the below:

using(AesCryptoServiceProvider Aes = new AesCryptoServiceProvider()){
        Aes.Key = keyArray; 
        Aes.Mode = CipherMode.CBC; 
        Aes.Padding = PaddingMode.PKCS7; 
        Aes.IV = IV; 
        using (ICryptoTransform cTransform = Aes.CreateDecryptor()){
            byte[] resultArray = cTransform.TransformFinalBlock(toDecryptArray, 0, toDecryptArray.Length); 
            Aes.Clear(); 
            return UTF8Encoding.UTF8.GetString(resultArray, 0, resultArray.Length); 
        }
}
like image 53
HCL Avatar answered Dec 05 '22 10:12

HCL