Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# AES加密方法中的内存泄漏问题_C#_.net 3.5_Memory Leaks_Cryptography - Fatal编程技术网

C# AES加密方法中的内存泄漏问题

C# AES加密方法中的内存泄漏问题,c#,.net-3.5,memory-leaks,cryptography,C#,.net 3.5,Memory Leaks,Cryptography,请任何人确认以下代码中是否存在任何可能的内存泄漏。我曾尝试使用.Net内存探查器,它显示“CreateEncryptor”和其他一些函数正在留下非托管内存泄漏,因为我已使用性能监视器确认了这一点 但已经有处理,清除,关闭电话放置在任何可能的地方,请相应地通知我。这是一个紧急的问题 public static string Encrypt(string plainText, string key) { //Set up the encryption objects

请任何人确认以下代码中是否存在任何可能的内存泄漏。我曾尝试使用.Net内存探查器,它显示“CreateEncryptor”和其他一些函数正在留下非托管内存泄漏,因为我已使用性能监视器确认了这一点

但已经有处理,清除,关闭电话放置在任何可能的地方,请相应地通知我。这是一个紧急的问题

public static string Encrypt(string plainText, string key)
    {
        //Set up the encryption objects
        byte[] encryptedBytes = null;
        using (AesCryptoServiceProvider acsp = GetProvider(Encoding.UTF8.GetBytes(key)))
        {
            byte[] sourceBytes = Encoding.UTF8.GetBytes(plainText);
            using (ICryptoTransform ictE = acsp.CreateEncryptor())
            {
                //Set up stream to contain the encryption
                using (MemoryStream msS = new MemoryStream())
                {
                    //Perform the encrpytion, storing output into the stream
                    using (CryptoStream csS = new CryptoStream(msS, ictE, CryptoStreamMode.Write))
                    {
                        csS.Write(sourceBytes, 0, sourceBytes.Length);
                        csS.FlushFinalBlock();

                        //sourceBytes are now encrypted as an array of secure bytes
                        encryptedBytes = msS.ToArray(); //.ToArray() is important, don't mess with the buffer

                        csS.Close();
                    }

                    msS.Close();
                }
            }

            acsp.Clear();
        }

        //return the encrypted bytes as a BASE64 encoded string
        return Convert.ToBase64String(encryptedBytes);
    }
    private static AesCryptoServiceProvider GetProvider(byte[] key)
    {
        AesCryptoServiceProvider result = new AesCryptoServiceProvider();
        result.BlockSize = 128;
        result.KeySize = 256;
        result.Mode = CipherMode.CBC;
        result.Padding = PaddingMode.PKCS7;

        result.GenerateIV();
        result.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

        byte[] RealKey = GetKey(key, result);
        result.Key = RealKey;
        // result.IV = RealKey;
        return result;
    }

    private static byte[] GetKey(byte[] suggestedKey, SymmetricAlgorithm p)
    {
        byte[] kRaw = suggestedKey;
        List<byte> kList = new List<byte>();

        for (int i = 0; i < p.LegalKeySizes[0].MaxSize; i += 8)
        {
            kList.Add(kRaw[(i / 8) % kRaw.Length]);
        }
        byte[] k = kList.ToArray();
        return k;
    }
公共静态字符串加密(字符串明文、字符串密钥)
{
//设置加密对象
字节[]encryptedBytes=null;
使用(AESCryptServiceProvider acsp=GetProvider(Encoding.UTF8.GetBytes(key)))
{
byte[]sourceBytes=Encoding.UTF8.GetBytes(纯文本);
使用(ICryptoTransform ictE=acsp.CreateEncryptor())
{
//设置流以包含加密
使用(MemoryStream msS=新MemoryStream())
{
//执行加密,将输出存储到流中
使用(CryptoStream csS=新的CryptoStream(msS、ictE、CryptoStreamMode.Write))
{
Write(sourceBytes,0,sourceBytes.Length);
FlushFinalBlock();
//sourceBytes现在作为安全字节数组进行加密
encryptedBytes=msS.ToArray();//.ToArray()很重要,不要弄乱缓冲区
csS.Close();
}
msS.Close();
}
}
acsp.Clear();
}
//将加密字节作为BASE64编码字符串返回
返回Convert.tobase64字符串(encryptedBytes);
}
私有静态加密服务提供程序GetProvider(字节[]密钥)
{
AESCryptServiceProvider结果=新的AESCryptServiceProvider();
result.BlockSize=128;
result.KeySize=256;
结果.Mode=CipherMode.CBC;
result.Padding=PaddingMode.PKCS7;
result.GenerateIV();
result.IV=新字节[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
字节[]RealKey=GetKey(key,result);
result.Key=RealKey;
//result.IV=RealKey;
返回结果;
}
私有静态字节[]GetKey(字节[]suggestedKey,对称算法p)
{
字节[]kRaw=建议的密钥;
List kList=新列表();
对于(int i=0;i
更新:经过进一步调查后,我将此记录为一个bug。他们已经确认了这个错误,并创建了一个新的。(显然,这是一个修补程序,因此通常的免责声明适用。如果可以,升级到.net 4.0可能是首选解决方案)


这段代码似乎在.NET3.5中泄漏,但在.NET4.0中运行良好

我从.NET4.0开始,将您的代码复制到一个快速测试应用程序中,并调用了1000000次,整个过程中内存使用量始终保持在22.4mb。我还跟踪了GC堆大小和句柄计数,它们都保持不变。据我所知,代码没有泄漏

然后,我在.NET3.5下重建了应用程序并重新运行了测试,我得到了您描述的确切漏洞。它的初始容量约为24mb,到它拨打10万次电话时,内存使用量已经翻了一番,超过了50mb。有趣的是,Gen2堆似乎在增加,这表明它是托管内存泄漏,而不是非托管句柄/内存

如果可能的话,我建议您尝试切换到.NET4.0

我的完整代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace ConsoleApplication5
{
    class Program
    {
        static void Main(string[] args)
        {
            String encryptedString;


            for (int j = 0; j < 1000; j++)
            {
                for (int i = 0; i < 1000; i++)
                {
                    encryptedString = Encrypt(String.Format("test string {0} {1}", j, i), "key");
                }
                Console.WriteLine("j = {0}", j);
            }

            Console.WriteLine("Finished");
            Console.ReadLine();

        }

        public static string Encrypt(string plainText, string key)
        {
            //Set up the encryption objects
            byte[] encryptedBytes = null;
            using (AesCryptoServiceProvider acsp = GetProvider(Encoding.UTF8.GetBytes(key)))
            {
                byte[] sourceBytes = Encoding.UTF8.GetBytes(plainText);
                using (ICryptoTransform ictE = acsp.CreateEncryptor())
                {
                    //Set up stream to contain the encryption
                    using (MemoryStream msS = new MemoryStream())
                    {
                        //Perform the encrpytion, storing output into the stream
                        using (CryptoStream csS = new CryptoStream(msS, ictE, CryptoStreamMode.Write))
                        {
                            csS.Write(sourceBytes, 0, sourceBytes.Length);
                            csS.FlushFinalBlock();

                            //sourceBytes are now encrypted as an array of secure bytes
                            encryptedBytes = msS.ToArray(); //.ToArray() is important, don't mess with the buffer

                            csS.Close();
                        }

                        msS.Close();
                    }
                }

                acsp.Clear();
            }

            //return the encrypted bytes as a BASE64 encoded string
            return Convert.ToBase64String(encryptedBytes);
        }
        private static AesCryptoServiceProvider GetProvider(byte[] key)
        {
            AesCryptoServiceProvider result = new AesCryptoServiceProvider();
            result.BlockSize = 128;
            result.KeySize = 256;
            result.Mode = CipherMode.CBC;
            result.Padding = PaddingMode.PKCS7;

            result.GenerateIV();
            result.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

            byte[] RealKey = GetKey(key, result);
            result.Key = RealKey;
            // result.IV = RealKey;
            return result;
        }

        private static byte[] GetKey(byte[] suggestedKey, SymmetricAlgorithm p)
        {
            byte[] kRaw = suggestedKey;
            List<byte> kList = new List<byte>();

            for (int i = 0; i < p.LegalKeySizes[0].MaxSize; i += 8)
            {
                kList.Add(kRaw[(i / 8) % kRaw.Length]);
            }
            byte[] k = kList.ToArray();
            return k;
        }

    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Security.Cryptography;
使用System.IO;
命名空间控制台应用程序5
{
班级计划
{
静态void Main(字符串[]参数)
{
字符串加密字符串;
对于(int j=0;j<1000;j++)
{
对于(int i=0;i<1000;i++)
{
encryptedString=Encrypt(String.Format(“测试字符串{0}{1}”,j,i),“密钥”);
}
WriteLine(“j={0}”,j);
}
控制台。写入线(“完成”);
Console.ReadLine();
}
公共静态字符串加密(字符串明文、字符串密钥)
{
//设置加密对象
字节[]encryptedBytes=null;
使用(AESCryptServiceProvider acsp=GetProvider(Encoding.UTF8.GetBytes(key)))
{
byte[]sourceBytes=Encoding.UTF8.GetBytes(纯文本);
使用(ICryptoTransform ictE=acsp.CreateEncryptor())
{
//设置流以包含加密
使用(MemoryStream msS=新MemoryStream())
{
//执行加密,将输出存储到流中
使用(CryptoStream csS=新的CryptoStream(msS、ictE、CryptoStreamMode.Write))
{
Write(sourceBytes,0,sourceBytes.Length);
FlushFinalBlock();
//sourceBytes现在作为安全字节数组进行加密
encryptedBytes=msS.ToArray();//.ToArray()很重要,不要弄乱缓冲区
csS.Close();
}
msS.Close();
}
}
acsp.Clear();
}
//将加密字节作为BASE64编码字符串返回
返回Convert.tobase64字符串(encryptedBytes);
}
私有静态加密服务提供程序GetProvider(字节[]密钥)
{
Ae

/// 
        /// Encrypts a string
        /// 
        /// Text to be encrypted
        /// Password to encrypt with
        /// Salt to encrypt with
        /// Can be either SHA1 or MD5
        /// Number of iterations to do
        /// Needs to be 16 ASCII characters long
        /// Can be 128, 192, or 256
        /// An encrypted string
        public static string Encrypt(string PlainText, string Password,
            string Salt, string HashAlgorithm,
            int PasswordIterations, string InitialVector,
            int KeySize)
        {
            try
            {
                if (string.IsNullOrEmpty(PlainText))
                    return "";
                byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
                byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt);
                byte[] PlainTextBytes = Encoding.UTF8.GetBytes(PlainText);
                PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations);
                byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8);
                RijndaelManaged SymmetricKey = new RijndaelManaged();
                SymmetricKey.Mode = CipherMode.CBC;
                byte[] CipherTextBytes = null;
                using (ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes))
                {
                    using (MemoryStream MemStream = new MemoryStream())
                    {
                        using (CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write))
                        {
                            CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
                            CryptoStream.FlushFinalBlock();
                            CipherTextBytes = MemStream.ToArray();
                            MemStream.Close();
                            CryptoStream.Close();

                            CryptoStream.Dispose();
                            MemStream.Dispose();
                        }
                    }
                    Encryptor.Dispose();
                }
                SymmetricKey.Clear();
                return Convert.ToBase64String(CipherTextBytes);
            }
            catch { throw; }
        }