Handling secrets in .NET code

I had a question about handling private data such as a password in .NET code. I know this is a well documented area but I still get questions about stuff like this from time to time:

The risk associated with storing passwords or other sensitive data in a local program variable is that the memory image of those variables might be readable from another process after the operation has complete.

In native code programming it's a good practice to overwrite the contents of memory that has contained sensitive data immediately after it’s finished with. This technique will work for most types in .NET including numeric types, most array types and also the StringBuilder class. What makes this a little trickier with .NET is the Garbage Collector owns all the allocating and freeing of memory. Using GC introduces non deterministic destruction of variables and the consequential releasing of any memory, which means you cannot guarantee when the local 'password' variable is going to be destroyed and freed. Local variable memory could last well beyond the end of the method.

Probably the most interesting issue with private data arises because of the implementation of string handling with .NET. Strings in .NET are immutable. When a string is assigned a value the class code requests storage space for the new data value and stores it. If the program subsequently alters or extends the value of the string then a new allocation is requested rather than modifying the existing data area. This is done for several reasons including for performance - in .NET it's very quick to allocate new space. So consider this code:

String Password = GetPasswordFromUser();

retval = CheckPassword(Password);

Password = "xxxxxxxxxxxx"; // Clear the password string

The last line will never clear password data returned from GetPasswordFromUser() because it will result in a new allocation. Somewhere in the GC memory heap there will potentially be a copy of the password beyond the scope of the local procedure.

So what's the solution: If you can use .NET 2.0 for the desktop then there is a new class System.Security.SecureString that will store the string data encrypted and will guarantee to destroy its memory footprint when the object destructs.

For earlier .NET versions and for Compact Framework (that doesn't provide SecureString in V2.0), I would recommend you build your own secure string (or other data type) class that provides the level of protection your risk assessment requires. Inside your implementation of secure string use a StringBuilder instance, not a string instance and offer an explicit "Clear" method that walks the string array and overwrites with random data before destruction.

Marcus