Hi Gaurav Sharma here.......
I am a developer on the CISG India team based in Hyderabad and I joined Microsoft four months ago. I love playing computer games and recently finished Call of duty 4. For the last three years I've been working with .NET and have worked on different kinds of applications that include ERP solutions, utilities and web portals. Apart from computer games I like watching soccer; there was a time (long back) when I used to watch each and every match of English premier league. I've a blog that I last updated when I joined MS. This looks like enough information about me, let us start with our secure string story.
A few months back I was looking into improvements that Microsoft made to it's .NET base class library since its inception and I stumbled upon a class named Secure String. I found that exiting and made a small blog entry related to this new class. In this write up I'll try to focus on the need for secure string class as well as its internal working and usage. I'll also try to do a feature comparison between String and SecureString class. You will find code examples and IL code with theoretical explanations. There are a few tools that I will use for creating code and IL samples. These are:
The structure of this two part write up (this is part one) is as follows;
Let's start our journey to explore SecureString,
INTRODUCTION
Since the inception of .NET programming, I doubt whether there is any other class used more frequently than the String class. We can use string to represent any textual and literal data like name, location, occupation etc. There are four ways in which we can represent individual character and their collections:
System.String is an ordered set of characters that is immutable. String is a reference type so every string object that we create lives on the heap rather than on the thread stack. Because strings are immutable, once they are created we can not change them. We can not add or remove or manipulate existing string objects. Whenever we try to manipulate string objects we discard old objects (they are still there on heap) and create new ones. Let's see a code snippet,
1: using System;
2:
3: namespace Gaurav.Samples.SecureString
4: {
5: class Program
6: {
7: static void Main(string[] args)
8: {
9: string name = "Gaurav";
10: name = name + "Sharma";
11: name = name + "Mr.";
12: Console.WriteLine(name);
13: Console.Read();
14: }
15: }
16: }
This will create three string objects. When we add "Sharma" to the already existing string name, a new string object is created and the name variable now refers to this new object. The old string object is marked for garbage collection. Same thing happens again when we try to append "Mr." to name. A new object is created and we have two old objects marked for garbage collection. The next garbage collection run will clear out these two objects.
Now suppose you have a application that stores username, password and credit card number in string objects. These string objects are basically in memory character arrays and if there is any unsafe or unmanaged code is allowed to execute, that code can snoop around the process's address space, locate the string with sensitive data and can use this data in a bad way.
Strings are not pinned objects. Pinned objects are those whose memory can not be compacted by garbage collection. As strings are not pinned objects, our garbage collector is free to move strings in memory. When string objects are moved several garbage copies of string data are created whose memory will be reclaimed by the garbage collector during later runs. Having so many copies of data (especially if sensitive) can create issues.
String keeps a plain text copy i.e. not encrypted, so our data is under continuous danger of being read by some one who can read our process's memory. If our string object is used for a small time span and then garbage collected, it's possible that the common language runtime (CLR) will not reuse the object's memory immediately (this depends on the generation of the object). This can be a potentially compromising situation with our strings data left in memory. Moreover as strings are immutable you can not overwrite them with blank data, the code below for example will not clear out any data.
10: //this will create new object and will not clear out old object's data
11: name = "";
If at any time you run out of memory, string memory contents can get into SWAP files, where they can be a lot easier to access by the bad guys (hackers). Due to these issues Microsoft introduced added another secure string class in FCL,
SECURE STRING CLASS
Some facts about secure string class are:
MEMBERS
MSDN provides a good information about members of the SecureString class. http://msdn.microsoft.com/en-us/library/system.security.securestring_members.aspx page will give you enough information that will equip you for SecureString usage. For your convenience I'll add member summary here, but for latest information you should always check MSDN.
USAGE
There are not many examples that uses SecureString class so I'll try to show you where this class is used in the framework class library by developing a small application that uses secure string. To avoid complications our sample application will be a small (micro) console application that stores passwords in secure string and renders it to console. Let's start with knowing about FCL usage of SecureString class,
Below I've added what's probably the most exhaustive list of SecureString usage you will ever find on web. Some of these uses secure string internally and some of them are not public. You will find a list of places where SecureString is used, places where SecureString objects are exposed, where SecureString objects are initialised and assemblies on which SecureString depends. Now let's move to our sample application.
Below I've added what's probably the most exhaustive list of SecureString usage you will ever find on web. Some of these uses secure string internally and some of them are not public. You will find a list of places where SecureString is used, places where SecureString objects are exposed, where SecureString objects are initialised and assemblies on which SecureString depends.
Now let's move to our sample application.
2: using System.Security; //required for SecureString
3: using System.Runtime.InteropServices; //required for SecureString
4:
5: namespace Gaurav.SecureStringSamples.ConsoleLoginSample
7: class Program
9: static void Main(string[] args)
10: {
11: using (SecureString password = new SecureString())
12: {
13: ConsoleKeyInfo consoleKeyInfo; //used to read console keys
14: Console.Write("Please enter password: ");
15: while (true)
16: {
17: consoleKeyInfo = Console.ReadKey(true);
18: if (consoleKeyInfo.Key == ConsoleKey.Enter) break;
19: password.AppendChar(consoleKeyInfo.KeyChar);
20: Console.WriteLine("*");
21: }
22: Console.WriteLine();
23: RenderSecureString(password);
24: Console.Read();
25: }
26: Console.WriteLine("done");
27: Console.Read();
28: }
29: private unsafe static void RenderSecureString(SecureString toBeDisplayedSecureStr)
30: {
31: Char* charPtr = null;
32: try
33: {
34: //cast int ptr to char ptr
35: //copy content from secure string to block of unmanaged memory
36: charPtr = (Char*)Marshal.SecureStringToCoTaskMemUnicode(toBeDisplayedSecureStr);
37: for (Int32 count = 0; count < toBeDisplayedSecureStr.Length; count++) Console.Write(charPtr[count]);
38: }
39: finally
40: {
41: //frees unmanaged string pointer allocated by Marshal.SecureStringToCoTaskMemUnicode
42: if (charPtr != null) Marshal.ZeroFreeCoTaskMemUnicode((IntPtr)charPtr);
43: }
44: }
45: }
46: }
Cool, we have now created our very first secure string example. Next time I'll add some performance tests to this example and compare them with the standard string class. Stay tuned!
Cool, we have now created our very first secure string example. Next time I'll add some performance tests to this example and compare them with the standard string class.
Stay tuned!