Clear C# String from memory

raisyn picture raisyn · Aug 27, 2015 · Viewed 11.2k times · Source

I'm trying to clear the memory contents of a C# string for security reasons. I'm aware of the SecureString class, but unfortunately I cannot use SecureString instead of String in my application. The strings which need to be cleared are created dynamically at runtime (e.g. I'm not trying to clear string literals).

Most search result I found basically stated that clearing the contents of a String is not possible (as string are immutable) and SecureString should be used.

Therefore, I did come up with my own solution (using unsafe code) below. Testing shows that the solutions works, but I'm still not sure if there is anything wrong with the solution? Are there better ones?

static unsafe bool clearString(string s, bool clearInternedString=false) 
{
    if (clearInternedString || string.IsInterned(s) == null)
    {
        fixed (char* c = s)
        {
            for (int i = 0; i < s.Length; i++)
                c[i] = '\0';
        }
        return true;
    }
    return false;
}

EDIT: Due to the comments on the GC moving the string around before clearString gets called: what about the following snippet?

string s = new string('\0', len);
fixed (char* c = s)
{
    // copy data from secure location to s
    c[0] = ...;
    c[1] = ...;
    ...

    // do stuff with the string

    // clear the string
    for (int i = 0; i < s.Length; i++)
        c[i] = '\0';
}

Answer

kemiller2002 picture kemiller2002 · Aug 27, 2015

Your problem with this is that strings can move. If the GC runs, it can move the contents to a new location, but it won't zero out the old one. If you did zero out the string in question, you have no guarantee that a copy of it doesn't exist elsewhere in memory.

Here is a link to the .NET Garbage Collector, and it talks about compacting.

EDIT: here's your problem with the update:

// do stuff with the string

The problem is that once it leaves your control, you lose the ability to make sure that it's secure. If it was entirely in your control, then you wouldn't have the limitation of only using a string type. Simply put, this issue has been around for a long time, and no one has come up with a secure way of handling this. If you want to keep it secure, it's best handled through other means. Clearing out the string is meant to prevent someone from being able to find it through a memory dump. The best way to stop this if you can't use secure string is limit access to the machine the code is running on.