Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MemoryStream to SecureString: Wiping the memory

Tags:

c#

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?

like image 970
Chris Avatar asked Jun 11 '15 18:06

Chris


People also ask

How do I reuse MemoryStream?

You can re-use the MemoryStream by Setting the Position to 0 and the Length to 0. By setting the length to 0 you do not clear the existing buffer, it only resets the internal counters.

Why use SecureString?

Overall, SecureString is more secure than String because it limits the exposure of sensitive string data. However, those strings may still be exposed to any process or operation that has access to raw memory, such as a malicious process running on the host computer, a process dump, or a user-viewable swap file.

When to use Secure string in c#?

A SecureString object is similar to a String object in that it has a text value. However, the value of a SecureString object is automatically encrypted, can be modified until your application marks it as read-only, and can be deleted from computer memory by either your application or the .

Does MemoryStream copy byte array?

From expirience I can say, that it does not copy the array. Be aware though, that you are unable to resize the memory stream, when using an array in the constructor.


2 Answers

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.

like image 77
xxbbcc Avatar answered Sep 22 '22 01:09

xxbbcc


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.

like image 31
Zotta Avatar answered Sep 25 '22 01:09

Zotta