Recipe17.15.Protecting String Data with Secure Strings


Recipe 17.15. Protecting String Data with Secure Strings

Problem

You need to store sensitive information, such as a Social Security number, in a string. However, you do not want prying eyes to be able to view this data in memory.

Solution

Use the SecureString object. To place text from a stream object within a SecureString object, use the following method:

 public static SecureString CreateSecureString(StreamReader secretStream) {     SecureString secretStr = new SecureString();     char buf;     while (secretStream.Peek() >= 0)     {         buf = (char)secretStream.Read();         secretStr.AppendChar(buf);     }     // Make the secretStr object read-only.     secretStr.MakeReadOnly();     return (secretStr); } 

To pull the text out of a SecureString object, use the following method:

 public static void ReadSecureString(SecureString secretStr) {     // In order to read back the string, you need to use some special methods.     IntPtr secretStrPtr = Marshal.SecureStringToBSTR(secretStr);     string nonSecureStr = Marshal.PtrToStringBSTR(secretStrPtr);     // Use the unprotected string.     Console.WriteLine("nonSecureStr = {0}", nonSecureStr);     Marshal.ZeroFreeBSTR(secretStrPtr);     if (!secretStr.IsReadOnly())     {         secretStr.Clear();     } } 

Discussion

A SecureString object is designed specifically to contain string data that you want to keep secret. Some of the data you may want to store in a SecureString object would be a Social Security number, a credit card number, a PIN number, a password, an employee ID, or any other type of sensitive information.

This string data is automatically encrypted immediately upon being added to the SecureString object, and it is automatically decrypted when the string data is extracted from the SecureString object. The encryption is one of the highlights of using this object. In addition to encryption, there will be only one copy of a SecureString object in memory at any one time. This is in direct contrast to a String object, which creates multiple copies in memory whenever the text in the String object is modified.

Another feature of a SecureString object is that when the MakeReadOnly method is called, the SecureString becomes immutable. Any attempt to modify the string data within the read-only SecureString object causes an InvalidOperationException to be thrown. Once a SecureString object is made read-only, it cannot go back to a read/write state. However, you need to be careful when calling the Copy method on an existing SecureString object. This method will create a new instance of the SecureString object on which it was called, with a copy of its data. However, this new SecureString object is now readable and writable. You should review your code to determine if this new SecureString object should be made read-only similarly to its original SecureString object.

The SecureString object can be used only on Windows 2000 (with Service Pack 3 or greater) or later operating system


In this recipe you create a SecureString object from data read in from a stream. This data could also come from a char* using unsafe code. The SecureString object contains a constructor that accepts a parameter of this type in addition to an integer parameter that takes a length value, which determines the number of characters to pull from the char*.

Getting data out of a SecureString object is not obvious at first glance. There are no methods to return the data contained within a SecureString object. In order to accomplish this, you must use two static methods on the Marshal class. The first is the SecureStringToBSTR, which accepts your SecureString object and returns an IntPtr. This IntPtr is then passed into the PtrToStringBSTR method, also on the Marshal class. The PtrToStringBSTR method then returns an unsecure String object containing your decrypted string data.

Once you are done using the SecureString object, you should call the static ZeroFreeBSTR method on the Marshal class to zero out any memory allocated when extracting the data from the SecureStirng. As an added safeguard, you should call the Clear method of the SecureString object to zero out the encrypted string from memory. If you have made your SecureString object read-only, you will not be able to call the Clear method to wipe out its data. In this situation, you must either call the Dispose method on the SecureString object or rely on the garbage collector to remove the SecureString object and its data from memory.

Notice that when you pull a SecureString object into an unsecure String, its data becomes viewable by a malicious hacker. So it may seem pointless to go through the trouble of using a SecureString when you are just going to convert it into an unsecure String. However, by using a SecureString, you narrow the window of opportunity for a malicious hacker to view this data in memory. In addition, some APIs accept a SecureString as a parameter so that you don't have to convert it to an unsecure String. The ProcessStartInfo, for example, accepts a password in its Password property as a SecureString object.

The SecureString object is not a silver bullet for securing your data. It is, however, another layer of defense you can add to your application.


See Also

See the "SecureString Class" topic in the MSDN documentation.



C# Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2004
Pages: 424

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net