Может любой определить является там любыми возможными утечками памяти в следующем коде. Я попробовал.Net Memory Profiler, и он говорит, что "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;
}
Обновление : после дополнительного расследования я зарегистрировал это как ошибку на Microsoft connect . Они признали ошибку и создали исправление . (Очевидно, что это исправление, поэтому применяются обычные заявления об отказе от ответственности. Если вы можете, обновление до .net 4.0, вероятно, было бы предпочтительным решением)
Похоже, что этот код просачивается в .net 3.5, но отлично работает в .net 4.0.
Я начал с .net 4.0 и скопировал ваш код в приложение для быстрого тестирования и вызвал его 1000000 раз, при этом использование памяти оставалось постоянным на уровне 22,4 МБ все время. Я также отслеживал размеры кучи GC и количество дескрипторов, и все они оставались неизменными. Насколько я могу судить, этот код не протекает.
Затем я перестроил приложение под .net 3.5 и повторно запустил тест, и я получил точную утечку, которую вы описываете. Он начинался с 24 Мбайт, а к тому времени, когда было совершено 100 000 вызовов, использование памяти увеличилось вдвое и превысило 50 Мбайт. Интересно, что, похоже, увеличивалась куча Gen2, что говорит о том, что это утечка управляемой памяти, а не неуправляемые дескрипторы / память.
Если возможно, я бы посоветовал вам попробовать перейти на .net 4.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;
}
}
}
Не пытаюсь захватить тему, но в чем основная разница между вашим шифром и этим?
///
/// 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; }
}
Я запустил этот под 3.5 и он не сдвинулся дальше 22мб. Мои навыки в криптографии невелики, но мне просто интересно, почему один лучше другого, и так ли это. Кажется, есть много способов делать одно и то же.