The SecureString class is new in the System.Security namespace with the .NET v2.0 upgrade. SecureString keeps sensitive data encrypted in memory so that it cannot be easily stolen. SecureString plugs a specific security hole but does not guard against all threats while securing information in applications.

What is SecureString?

SecureString is a .NET object that secures text which must be kept confidential, such as passwords, pin codes, credit card and social security numbers. The text is encrypted in memory for privacy when it’s being used, and is deleted from computer memory when it’s no longer needed.

Safe from Forensics

With SecureString, the original unencrypted text never appears in memory, hence it cannot be recovered using forensic analysis. For example, when a user types her password to login an application, typically the password characters appear on the screen as bullets or asterisks. This prevents someone from stealing a password by looking over the user’s shoulder.

But even though the password is not visible to the human eye, it is normally stored in plain text in the computer’s memory. Given the nature of Windows memory management, it’s quite possible the application’s memory–and hence the plain text password–could be written to disk in the Windows swap file. Such data can remain there for days or even years. A hacker, spy or prying roommate could then search your hard drive for passwords and other sensitive data. But SecureString keeps its text encrypted while in memory, and hence protected even if written to disk.

Vulnerable to Surveillance

Unfortunately, SecureString will not protect users from computer surveillance. If someone is watching your PC using spyware, keystroke logger, hidden camera or remote monitor, then sensitive data may be compromised before it ever enters the SecureString object. Using the password example above, a keystroke logger would record each key the user pressed to steal her passwords and other sensitive data. So it’s irrelevant that SecureString encrypts her password after it has already been stolen.

Populate a SecureString

The first thing you will notice about the SecureString class is that there is no easy way to get or set the unencrypted text… no Text property or ToString method. This helps prevent you from representing sensitive text in its unencrypted form, otherwise the protection offered by SecureString is lost immediately. Instead, you populate a SecureString with one of the following methods:

  • AppendChar – Adds one character to the end of the string.
  • InsertAt – Inserts a character at a specific position in the string.
  • RemoveAt – Removes a character at a specific position in the string.
  • SetAt(int,char) – Sets a character at a specific position in the string.

For example, to initialize a secure string with “Test”:

SecureString ss = new SecureString();
ss.AppendChar( 'T' );
ss.AppendChar( 'e' );
ss.AppendChar( 's' );
ss.AppendChar( 't' );

SecureString Components

The approach above is not advised because the individual characters may be stored together in the application and can be viewed in a memory or code dump. Instead, the AppendChar method is better suited to reading passwords and other sensitive data from the user.

Here are some very useful .NET components that employ SecureString:

Use a SecureString

SecureString uses the Data Protection API (DPAPI), so it only works on Windows NT or newer systems.

As mentioned above, there is no easy way to extract the unencrypted text from a SecureString. Instead, you must use one of the Marshall class’ new static methods to copy the unencrypted text into unmanaged memory:

  • SecureStringToCoTaskMemAnsi
  • SecureStringToGlobalAllocAnsi
  • SecureStringToCoTaskMemUnicode
  • SecureStringToGlobalAllocUnicode
  • SecureStringToBSTR

Note that you have to be very careful how you use and represent the unencrypted data in memory, otherwise you risk forensic discovery!

Once you’ve used the unencrypted data, you must clear its unmanaged memory space. For example, if using BSTR pointers to unmanaged memory:

SecureString ss = new SecureString();
/* ... */
IntPtr bstr = Marshal.SecureStringToBSTR( ss );
try
{
    // use the bstr
}
finally
{
    if (bstr != IntPtr.Zero)
        Marshal.ZeroFreeBSTR( bstr );
}

Dispose a SecureString

The SecureString class implements the IDisposable interface, so you should explicitly call the string’s Dispose method when you are finished using it. Or you can use SecureString in context of a using statement that will automatically dispose the object, such as:

using (SecureString ss = new SecureString())
{
    // use the secure string
}

Note that SecureString inherits from the CriticalFinalizerObject abstract class. This ensures that the SecureString’s finalization code is marked as critical and always executes, even if the thread is terminated abnormally. As a result, the SecureString’s encrypted contents are properly erased from memory.