Working with SecureString






4.58/5 (19 votes)
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.