SecureString - System.Security.SecureString Class - Encrypting Strings in Memory in .NET 2.0 Framework
by David Hayden ( Florida .NET Developer )
In my previous post about the Enterprise Library 2.0 Cryptography Application Block, I briefly mentioned that you need to be careful about using a managed string to hold sensitive information that is normally encrypted. Here are the reasons you can find in any blog or book:
- It's not pinned, so the garbage collector can move it around at will leaving several copies in memory
- It's not encrypted, so anyone who can read your process' memory will be able to see the value of the string easily. Also, if your process gets swapped out to disk, the unencrypted contents of the string will be sitting in your swap file.
- It's not mutable, so whenever you need to modify it, there will be the old version and the new version both in memory
- Since it's not mutable, there's no effective way to clear it out when you're done using it
So... in the .NET 2.0 Framework we now have SecureString, which is located in System.Security, which doesn't suffer from the above problems.
If sorta suffers from another problem, it is not widely used at this point.
SecureString and DPAPI
However, the idea of a SecureString Class is great. The contents of SecureString is protected by DPAPI ( Data Protection API ), which means it's contents is encrypted all the time. It is also pinned in memory, which means the .NET Framework doesn't move it around. It is also mutable, which means 1) it can be cleared and 2) passing it around the framework doesn't cause several copies of the sensitive information to be floating around. Sweet idea.
SecureString Example
The only example one can really find using SecureString is the unrealistic sample of grabbing a password from the console characted by character. This example should be burned :)
/// <summary>
/// Read a password from the console into a SecureString
/// </summary>
/// <returns>Password stored in a secure string</returns>
public static SecureString GetPassword()
{
SecureString password = new SecureString();
// get the first character of the password
ConsoleKeyInfo nextKey = Console.ReadKey(true);
while(nextKey.Key != ConsoleKey.Enter)
{
if(nextKey.Key == ConsoleKey.BackSpace)
{
if(password.Length > 0)
{
password.RemoveAt(password.Length - 1);
// erase the last * as well
Console.Write(nextKey.KeyChar);
Console.Write(" ");
Console.Write(nextKey.KeyChar);
}
}
else
{
password.AppendChar(nextKey.KeyChar);
Console.Write("*");
}
nextKey = Console.ReadKey(true);
}
Console.WriteLine();
// lock the password down
password.MakeReadOnly();
return password
}
The only other example I have found is with starting a process:
ProcessStartInfo myProcess =
new ProcessStartInfo("my.exe");
myProcess.UserName = "...";
SecureString password = new SecureString();
password.AppendChar('1'); // repeat
myProcess.Password = password;
myProcess.UseShellExecute = false;
Process.Start(myProcess);
Conclusion
The SecureString Class is a great idea, but it doesn't have widespread adoption yet in the .NET 2.0 Framework. Still, it is good to be aware of the System.Security.SecureString Class if you find it practical and need to keep sensitive information encrypted in memory.
Source: David Hayden ( Florida .NET Developer )