tags:

views:

931

answers:

7

I have a c# byte[] containing sensitive data. What is the best way to clear it? How do I ensure that something like Array.Clear will not be optimized away?

+6  A: 

I cannot think of any circumstance in which a call to Array.Clear would ever be optimized away and even if it could it would only be optimized away in instances where your byte[] was cleared already.

Edit: Something else to consider would be finding out if the framework's SecureString implementation would be useful in your situation:

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 .NET Framework garbage collector

Andrew Hare
If no one can possibly read the array after it has been cleared, then can't the compiler optimize by not clearing it?
Gautam
As a point of order: when you say _compiler_ are you referring to the C# compiler or the JIT compiler?
Andrew Hare
A: 

If you're concerned about Array.Clear, you could always just Marshal.Copy an empty byte array onto the sensitive data.

For example, like this (assuming 'data' is the byte[] containing the sensitive information):

        byte[] clear = new byte[data.Length];
        unsafe
        {
            fixed (byte* ptr = &data[0])
            {
                Marshal.Copy(clear, 0, new IntPtr(ptr), data.Length);
            }
        }
Preetum Nakkiran
A: 

I was under the impression that there were already techniques to show the recent state of RAM. Then there's also the MIT guys that flash froze some RAM, lifted it and took it somewhere else and maintained all of the state.

So, if you were paranoid, you'd randomly write a whole bunch of data over your array a few times.

Esteban Araya
They did do that. However that attack assumes access to the physical system. Defence in depth...
Spence
The real lesson is that you don't put secrets on your client, as your client can always be compromised.
Spence
@Spence: Yeah, I just think it's crazy they can do that. :)
Esteban Araya
A: 

AFAIK there is no equivalent to SecureZeroMemory in CLR. You should use SecureString to store your data.

Remus Rusanu
+2  A: 

Even if Array.Clear is guarenteed to be executed (not optimized away) I think you still may have a problem. The GC can move objects around in the heap and there is no guarentee that traces of the original byte will linger if it was moved from one location to another before Array.Clear was called.

You may want to check out SecureString, ProtectedData, or ProtectedMemory. But, if you want a more manual approach I think you are going to have to at least pin the byte array so that the GC cannot move it around. I believe the SecureString uses this trick as well.

Brian Gideon
A: 

A trick that works with most C compilers is to do something like sum all the elements of the cleared array, and then do something with that sum, like print it or xor it with your return value. That way the dead code elimination won't eliminate the clearing of the array.

That said, are you sure that you only need to clear this array? Consider all the other places where the value may also have existed: a buffer in a form, string objects being passed around, key equivalent values in intermediate calculations, or paged out to disk. Zeroizing this one array only gets you 1% of the way there. You have to clear the entire key path.

Theran
+1  A: 

If you're writing your own encryption routine, my advice would be: don't. You'll get it wrong (as would I, as would anyone who's not a security expert). Use a well-known, tested library.

(If not, never mind!) :)

TrueWill