MemoryStream to SecureString: Wiping the memory
I am retrieving an unencrypted
key from a MemoryStream
, converting it to some kind of string, and using that string with .Net's crypto
functions to encrypt data. I need to make sure the unencrypted
key is wiped from memory after using it. I found SecureString
, which I think will take care of the string, but I'm not sure how to wipe the memory of the key before it becomes a SecureString
.
So the way everything works is:
MemoryStream -> char[] -> SecureString
SecureString
is passed the pointer to the char array, so it wipes the char array when it is finished? This is it's constructor:
SecureString(Char*,int32)
There is an example implementing it here.
However, once the SecureString
wipes the data (if it wipes the data), I still need to know how to wipe the data in the MemoryStream
, and any intermediate objects I have to create in order to get the char[]
.
So this question boils down to two parts:
How does one read a MemoryStream
straight into a char[]
without producing anything else in memory? (And if that isn't possible, what is the ideal transition? ie, MemoryStream -> string -> char[]
?)
and,
How does one overwrite the memory used by the MemoryStream
(and any other signatures created in the MemStream->char[]
process) when finished?
First of all, SecureString
doesn't wipe the memory of the input char*
- you're responsible for that. It will only clean up its own internal storage.
To read/clean the contents of the MemoryStream
into a local char[]
, you can simply allocate the array (assuming that your stream contains a valid string):
// Get the contents of the stream.
var byKey = oMS.GetBuffer ();
fixed ( byte *pBytes = byKey )
{
var oSecStr = new SecureString ( (char*) pBytes,
(int) ( oMS.Length / 2 ) );
// Clear stream (there's no separate char/byte array
// to clean).
Array.Clear ( byKey, 0, byKey.Length );
}
This all, of course, assumes unsafe
code. There's, however, no fully guaranteed way to clear all potential instances of the key from memory - during the calls to get the key into the stream, it may be copied a number of times (in various private buffers you have no access to) so you probably won't even know the number of copies lingering around.
What you are trying is more problematic than you might think. A MemoryStream is most likely used by something else and most likely grows in size over time.
Every time it grows, the data is copied into a new array internally and the old one is freed => your key could leak here
Also, a MemoryStream is most likely used by some other API. The other APIs will most likely not securely delete the key, because they are not designed to do so.
But to answer your original question: If the key is just ascii characters, you can just copy the bytes into a char array and overwrite the original bytes with random junk. You can acces its contents directly using GetBuffer
.