Introduction
Often, String
objects are used to contain sensitive data such as a user’s password or creditcard information. Unfortunately, String
objects contain an array of characters in memory, and if some unsafe or unmanaged code is allowed to execute, the unsafe/unmanaged code could snoop around the process’s address space, locate the string
containing the sensitive information, and use this data in an unauthorized way. Even if the String
object is used for just a short time and then garbage collected, the CLR might not immediately reuse the String
object’s memory (especially if the String
object was in an older generation), leaving the String
’s characters in the process’s memory, where the information could be compromised. In addition, since string
s are immutable, as you manipulate them, the old copies linger in memory and you end up with different versions of the string
scattered all over memory.
Background
Some governmental departments have stringent security requirements that require very specific security guarantees. To meet these requirements, Microsoft added a more secure string
class to the FCL: System.Security.SecureString
.
Using the Code
When you construct a SecureString
object, it internally allocates a block of unmanaged memory that contains an array of characters. Unmanaged memory is used so that the garbage collector isn’t aware of it.
These string
’s characters are encrypted, protecting the sensitive information from any malicious unsafe/unmanaged code. You can append, insert, remove, or set a character in the secure string
by using any of these methods: AppendChar
, InsertAt
, RemoveAt
, and SetAt
. Whenever you call any of these methods, internally, the method decrypts the characters, performs the operation in place, and then re-encrypts the characters. This means that the characters are in an unencrypted state for a very short period of time. This also means that the performance of each operation is less than stellar, so you should perform as few of these operations as possible.
Here is some sample code demonstrating how to initialize and use a SecureString
(when compiling this, you’ll need to specify the /unsafe switch
to the C# compiler):
using System;
using System.Security;
using System.Runtime.InteropServices;
public static class Program {
public static void Main() {
using (SecureString ss = new SecureString()) {
Console.Write("Please enter password: ");
while (true) {
ConsoleKeyInfo cki = Console.ReadKey(true);
if (cki.Key == ConsoleKey.Enter) break;
ss.AppendChar(cki.KeyChar);
Console.Write("*");
}
Console.WriteLine();
DisplaySecureString(ss);
}
}
private unsafe static void DisplaySecureString(SecureString ss) {
Char* pc = null;
try {
pc = (Char*) Marshal.SecureStringToCoTaskMemUnicode(ss);
for (Int32 index = 0; pc[index] != 0; index++)
Console.Write(pc[index]);
}
finally {
if (pc != null)
Marshal.ZeroFreeCoTaskMemUnicode((IntPtr) pc);
}
}
}
The SecureString
class implements the IDisposable
interface to provide an easy way to deterministically destroy the string
’s secured contents. When your application no longer needs the sensitive string
information, you simply call SecureString
’s Dispose
method. Internally, Dispose
zeroes out the contents of the memory buffer to make sure that the sensitive information is not accessible to malicious code, and then the buffer is freed.
Points of Interest
In version 4 of the .NET Framework, you can pass a SecureString
as a password when:
- Working with a cryptographic service provider (CSP) - See the
System.Security.Cryptography.CspParameters
class. - Starting a new process under a specific user account - See the
System.Diagnostics.ProcessStartInfo
classes. - Constructing an event log session. See the
System.Diagnostics.Eventing.Reader.EventLogSession
class. - Using the
System.Windows.Controls.PasswordBox
control. See this class’s SecurePassword
property.
http://msdn.microsoft.com/en-us/library/system.security.securestring.aspx
History
- 6th November, 2011 – Initial version