I create a MemoryStream
, pass it to CryptoStream
for writing. I want the CryptoStream
to encrypt, and leave the MemoryStream
open for me to then read into something else. But as soon as CryptoStream
is disposed, it disposes of MemoryStream
too.
Can CryptoStream
leave the base MemoryStream
open somehow?
using (MemoryStream scratch = new MemoryStream())
{
using (AesManaged aes = new AesManaged())
{
// <snip>
// Set some aes parameters, including Key, IV, etc.
// </snip>
ICryptoTransform encryptor = aes.CreateEncryptor();
using (CryptoStream myCryptoStream = new CryptoStream(scratch, encryptor, CryptoStreamMode.Write))
{
myCryptoStream.Write(someByteArray, 0, someByteArray.Length);
}
}
// Here, I'm still within the MemoryStream block, so I expect
// MemoryStream to still be usable.
scratch.Position = 0; // Throws ObjectDisposedException
byte[] scratchBytes = new byte[scratch.Length];
scratch.Read(scratchBytes,0,scratchBytes.Length);
return Convert.ToBase64String(scratchBytes);
}
My simple solution:
You can but you will not be able to use using statements. You will need to manually manage the disposing of the object and you will also need to call
FlushFinialBlock()
to make sure all the data was written out to the underlying stream before working on it.Once all you are done working with the stream you can then dispose all of the resources you where waiting on in the finally block at the end.
As of .NET 4.7.2, there is a second constructor with an added bool parameter called
leaveOpen
. If this is set to true then theCryptoStream
's dispose method will not call dispose on the underlying stream.Additionally, the other constructor without the
leaveOpen
parameter simply forwards the parameters to the new constructor withleaveOpen
set tofalse
.MSDN
CryptoStream.Dispose(bool disposing)
It turns out, there isn't any need to break apart the using {} block into try{}finally{} ... Ultimately, you just have to use FlushFinalBlock() inside the using statement, and nest anything else inside there as necessary.
As a second solution, you can make a WrapperStream object that simply passes every call along except for Dispose / Close. Make a wrapper around your memory stream, hand the wrapper to the crypto stream, and now closing the crypto stream does not touch the memory stream.