65.9K
CodeProject is changing. Read more.
Home

Working with SecureString

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.58/5 (19 votes)

Feb 19, 2013

CPOL

3 min read

viewsIcon

185184

Handling confidential information using SecureString class.

Introduction

SecureString represents text that should be kept confidential. The text is encrypted for privacy when being used, and deleted from computer memory when no longer needed. This class cannot be inherited.

Background

We all are aware that the System.String class is immutable. Once after using it if we don't need it anymore, it cannot be programmatically scheduled for garbage collection; that is, the instance is read-only after it is created and it is not possible to predict when the instance will be deleted from the memory.

As a result, it is risky to store sensitive information such as a password, credit card number, or personal data within a string object. There is a risk of information being revealed after it is used because your application cannot delete data from computer memory.

To come over such a scenario, MS has introduced an additional object SecureString which is very similar to a String object and stores a text value. However, the value of a SecureString object is automatically encrypted, can be modified until your application marks it as read-only, and can be deleted from computer memory by either your application or the .NET Framework garbage collector.

The value of an instance of SecureString is automatically encrypted when the instance is initialized or when the value is modified. Your application can render the instance immutable and prevent further modification by invoking the MakeReadOnly method.

Using the code

The example below demonstrates how to use SecureString to secure a user's password for use as a credential to start a new process.

Let's create a sample console application, and add a class Misc.

I will be writing a simple method to assign a string text to the secure string and check whether the data remains confidential.

public class Misc
{
    // Instantiate the secure string.
    SecureString securePwd = new SecureString();

    public  SecureString  convertToSecureString(string strPassword)
    {
        var secureStr = new SecureString();
        if (strPassword.Length > 0)
            {
                foreach (var c in strPassword.ToCharArray()) secureStr.AppendChar(c);
            }
        return secureStr;
    }

In the above code, we are taking a string parameter and copying it to SecureString and sending the SecureString object.

Now, we will go ahead and call this method from our program.cs file.

class Program
{
    static void Main(string[] args)
    {
        SecureString sec_strPassword = new SecureString();
        string strPassword = "ZAQ!2wsx";

        Console.WriteLine("Secure String Example..");
        Console.WriteLine("Password : " +  strPassword.ToString());

        if (strPassword.Length > 0)
        {
            Misc miscObj = new Misc();
            SecureString secureString = new SecureString();

            //Converting UnSecure String to Secure String
            sec_strPassword = miscObj.convertToSecureString(strPassword);

            //Clearing strPassword Text
            strPassword = "";

            //Confirm Converstion, and Trying to retrieve Secure String Information 
            Console.WriteLine("Password converted to Secure Password : " + sec_strPassword.ToString());
            Console.WriteLine("Cleared actual Password : " + strPassword.ToString());
        }
    }
}

Rebuild the application, and execute it. You will see the below output:

Secure String Example
Password : ZAQ!2wsx
Password converted to Secure Password : System.Security.SecureString()
Cleared actual Password : 

The password information string which we copied to the SecureString object is not exposing the text within it. Instead, it returns the object type. By this, we are sure that our sensitive information is hidden now.

I am going to write another method to retrieve the encrypted SecureString information back to the string variable. Edit the Misc.cs file and add the below code:

public string convertToUNSecureString(SecureString secstrPassword)
{
    IntPtr unmanagedString = IntPtr.Zero;
    try
    {
        unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(secstrPassword);
        return Marshal.PtrToStringUni(unmanagedString);
    }
    finally
    {
        Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
    }
}

We will be calling this method from our program.cs file:

static void Main(string[] args)
{
    SecureString sec_strPassword = new SecureString();
    string strPassword = "ZAQ!2wsx";

    Console.WriteLine("Secure String Example..");
    Console.WriteLine("Password : " +  strPassword.ToString());

    if (strPassword.Length > 0)
    {
        Misc miscObj = new Misc();
        SecureString secureString = new SecureString();

        //Converting UnSecure String to Secure String
        sec_strPassword = miscObj.convertToSecureString(strPassword);

        //Clearing strPassword Text
        strPassword = "";

        //Confirm Converstion, and Trying to retrieve Secure String Information 
        Console.WriteLine("Password converted to Secure Password : " + sec_strPassword.ToString());
        Console.WriteLine("Cleared actual Password : " + strPassword.ToString());

        //Converting Secure String to UnSecure String.
        strPassword = miscObj.convertToUNSecureString(sec_strPassword);
        
        //Confirm Converstion: You can see the String output
        Console.WriteLine("Copied Un Secured password from Secure Password : " + strPassword.ToString());

        Console.ReadKey(true);
    }
}

Rebuild the application, and Execute it. You will now see the below output.

Secure String Example
Password : ZAQ!2wsx
Password converted to Secure Password : System.Security.SecureString()
Cleared actual Password : 
Copied Un Secured password from Secure String : ZAQ!2wsx

Here, we are able to retrieve our sensitive information from the SecureString object.

Finally, let's do another quick check with the SecureString object.

We will be modifying our Main code to start a new process by passing Domain, User, Password, and Process Name. The process will be triggered if the information passed is successfully authenticated. I will add this code in our Main program:

try
{
    //Passing Secure string to Initiate New Process, This line below will start a new 
    //Notepad Instance if the User and Password authenticates correctly.
    Process.Start("Notepad.exe", "Harry.s", sec_strPassword, "MYDOMAIN");
}
catch (Win32Exception e)
{
    Console.WriteLine(e.Message);
}

Let's do a final run to see what this will do. You will notice a new Notepad window appear once the process authenticates the information passed.

Working with SecureString - CodeProject