Тем не менее проблема "множественного удаления", хотя и решена
В некоторых моих проектах я использовал пару проверенных и надежных методов шифрования / дешифрования данных (метод шифрования приведен ниже). Но меня всегда преследовало это надоедливое предупреждение CA2202 ("Не удаляйте объекты несколько раз") об объекте memoryStream. Я считаю, что справляюсь с этим надлежащим образом, но я все равно получаю предупреждение всякий раз, когда запускаю анализ в Visual Studio. Это никогда не вызывает исключений в производственном коде, но я все же хотел бы избавиться от предупреждения раз и навсегда. Это возможно? Или я должен просто игнорировать это? Заранее спасибо.
public static string Encrypt(string clearText, string passPhrase, string saltValue)
{
byte[] clearTextBytes = Encoding.UTF8.GetBytes(clearText);
byte[] saltValueBytes = Encoding.UTF8.GetBytes(saltValue);
Rfc2898DeriveBytes passPhraseDerviedBytes = new Rfc2898DeriveBytes(passPhrase, saltValueBytes);
byte[] keyBytes = passPhraseDerviedBytes.GetBytes(32);
byte[] initVectorBytes = passPhraseDerviedBytes.GetBytes(16);
RijndaelManaged symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC };
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
byte[] cipherTextBytes = null;
MemoryStream memoryStream = null;
try
{
memoryStream = new MemoryStream();
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(clearTextBytes, 0, clearTextBytes.Length);
cryptoStream.FlushFinalBlock();
cipherTextBytes = memoryStream.ToArray();
}
}
finally
{
if (memoryStream != null)
{
memoryStream.Dispose();
}
}
return Convert.ToBase64String(cipherTextBytes);
}
2 ответа
Это потому что CryptoStream
закрывает memoryStream
Вы используете конструктор
public CryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode)
: this(stream, transform, mode, false) {
}
какие звонки
public CryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode, bool leaveOpen) {
_stream = stream;
_leaveOpen = leaveOpen;
//...
}
_leaveOpen
а также _stream
позже используются в Dispose
protected override void Dispose(bool disposing) {
try {
if (!_leaveOpen) {
_stream.Close();
}
//...
}
}
Вы можете удалить memoryStream.Dispose();
или передать true
в качестве параметра для CryptoStream
конструктор
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write, true)) { }
Проблема в том, что призыв к CryptoStream.Dispose
Можно вызвать dispose по заданному потоку:
protected override void Dispose(bool disposing) { try { if (disposing) { if (!_finalBlockTransformed) { FlushFinalBlock(); } if (!_leaveOpen) { _stream.Close(); } } } ... }
Если вы используете конструктор, который принимает 4 параметра:
CryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode, bool leaveOpen)
Последний аргумент определяет, является ли поток закрытым или нет. призвание Close()
, в свою очередь, по умолчанию также вызывает Dispose
:
public virtual void Close() { /* These are correct, but we'd have to fix PipeStream & NetworkStream very carefully. Contract.Ensures(CanRead == false); Contract.Ensures(CanWrite == false); Contract.Ensures(CanSeek == false); */ Dispose(true); GC.SuppressFinalize(this); }
Таким образом, кажется, что проверка не может правильно определить, будет ли конкретная реализация Stream удалена или нет, и вернется к мысли, что так и будет, что и есть.
Обратите внимание, однако, что удаление дважды, один раз или ноль раз MemoryStream
не имеет большого значения в большинстве случаев.