Jeff Griffin

SecureString: Soup to Nuts, Part II

Posted on April 11, 2011

My last post, SecureString: Soup to Nuts, Part I, dealt with some basic rules around using the SecureString class in .NET and how to prepare the secret stored inside for persistence, without exposing the clear text to a CLR type.  In the second part, I'm going to discuss my solution for maintaining SecureString best practices, without sacrificing our MVVM design principles.  The XAML and code provided is in WPF, but it's applicable to Silverlight, as well with minimal tinkering.

First let's talk about PasswordBox.  The PasswordBox was designed to obscure the user-entered text, both visually and in memory.  That is to say, visually, it's much like the old Windows Forms MaskedTextBox, except it's specifically designed for secret data, and will only expose said secret in a clear text string if asked to do so,via the Password property.  It's important to understand that the Password property is only a helper that accesses the encrypted data member.  For this reason, it is not exposed as a DependencyProperty.  This is a source of frustration to developers who have no designs on a SecureString solution.  Alas, there's no pleasing everyone, and a Password DependencyProperty would make an acceptable SecureString implementation impossible with PasswordBox.  If you Google "PasswordBox MVVM" (without the quotes) you will find that the generally accepted solution for the CLR string camp, makes use of an attached property to expose a CLR string for binding.  This effectively takes the MaskedTextBox functionality of PasswordBox, and passes on memory security.

We want an MVVM solution that hands us a SecureString, so let's look at the SecurePassword property.  More frustration, as this is also not a DependencyProperty.  Before you go angrily writing an attached property to expose the SecureString, understand that this is by design, not neglect.  The first commandment of SecureString is to dispose of it when you're finished right?  The SecurePassword property gives us a SecureString to use one time, then dispose of it.

The MVVM way to do this is now staring us in the face.  We need to bind the event we're going to use to execute our users' credentials to an ICommand.


<PasswordBox x:Name="_passwordBox" ...>
        …
        <PasswordBox.InputBindings>
                <KeyBinding Key="Enter" Command="{Binding ExecuteCredentialsCommand}"
                                 CommandParameter="{Binding ElementName=_passwordBox}" />
            </PasswordBox.InputBindings>
</PasswordBox>
<Button Content="Login Button Text" …
        Command="{Binding ExecuteCredentialsCommand}"
        CommandParameter="{Binding ElementName=_passwordBox}"/>

In this example's ViewModel, I'm using Prism's DelegateCommand implementation of ICommand.


public ViewModelClassConstuctor(IRegionManager regionManager,
	IProxyDataProvider dataProvider)
{
	ExecuteCredentialsCommand = new DelegateCommand(
	//execute method
	delegate(object parameter)
	{
		SecureString securePassword = parameter as SecureString;
		if (parameter is PasswordBox)
			securePassword = ((PasswordBox)parameter).SecurePassword;
		try
		{
			//authentication/persistence model code
		}
		finally
		{
                    		securePassword.Dispose();
		}

                },
	//can execute method
	delegate(object parameter)
            {
		SecureString securePassword = parameter as SecureString;
		if (parameter is PasswordBox)
                        	securePassword = ((PasswordBox)parameter).SecurePassword;
		return securePassword != null && securePassword.Length > 0 &&
			!string.IsNullOrEmpty(UserName);
	});
	CredentialsChangedCommand = new DelegateCommand(
	delegate
	{
		ExecuteCredentialsCommand.RaiseCanExecuteChanged();
	});
}

public DelegateCommand ExecuteCredentialsCommand { get; private set; }
public DelegateCommand CredentialsChangedCommand { get; private set; }

There you have it. With the code from the previous entry, you can generate a nice authentication prompt with password persistence, without sacrificing memory security or your MVVM design. I hope this has been a helpful guide. Please leave a comment if you liked it, have something you'd like to share, or if you thought it could have been more comprehensive.

SecureString: Soup to Nuts, Part I

Posted on April 4, 2011

Motivation:

Using the SecureString class in .NET is a great way to protect your users' sensitive data from malicious code, intended to pull said data right out of memory. It is already supported by framework classes that Internet enabled applications use often, like NetworkCredential, making its addition to your existing code fairly straightforward.

That's great, but since nothing is ever easy I want to point out that there are two scenarios where it wasn't so easy to accomplish requested functionality and maintain the proper use of SecureString:

  1. implementing secure local storage of a password, and
  2. preserving MVVM design without exposing the password in an insecure managed object.

There is quite a bit of widely accepted advice to be found on community support forums that seeks to fit each of these scenarios, but defeats the point of using SecureString at all.

As I understand it, there are two commandments one should follow if one intends to use them without sabotaging one's own efforts. The first is to dispose of the SecureString when processing is complete, the other is never to allow the unprotected contents of the SecureString to find its way into a CLR object, like a string or byte array. It just isn't clear how long they will be hanging around in memory, and heck, if you wanted to store your secret in a CLR string, you could have saved yourself a lot of time by doing so to begin with.

In part I and II of this article I will address my method of implementing solutions for these two scenarios, respectively.

Secure Local Storage:

Finally getting to the point.  This guy is first, because it's useful regardless of what design patterns or frameworks you're using to implement your interface, or whether you're implementing a GUI at all. If you've ever written a program that needs to utilize local storage for any data placed in a SecureString, you've run into this problem. The last thing you want to do is store it out in clear text, so you know it needs to be encrypted. DPAPI to the rescue. Great, but there's good news and bad news.

First the bad. The ProtectedData's Protect/Unprotect methods are staring us in the face, just begging us to use them, with their single parameter overloads, and be done. Alas, the second commandment of SecureStrings prevents us from placing our secret in a CLR byte array, so we're going to have to make the unmanaged calls to CryptoAPI.

The good news is that we can use P/Invokes and marshaling to accomplish the necessary unmanaged calls to CryptProtectData and CryptUnprotectData, zero out and free any sensitive data immediately without actually writing any unmanaged code.

Now for some code. Moving from an existing SecureString instance into some processing code is always going to look pretty similar to this...

IntPtr unmanagedString = Marshal.SecureStringToBSTR(self);
try
{
//Processing code here. Resist the urge to Marshal.PtrToStringBSTR.
}
finally
{
Marshal.ZeroFreeBSTR(unmanagedString); //free the buffer holding our secret
}

The rest of the solution is pretty plug-and-chug. I wrapped the CryptoAPI calls in SecureString extension methods GetProtectedData and AppendProtectedData found in this file. In the interest of leaving the method of storage as an implementation detail, the extension methods above export and import a byte array (encrypted of course). It's simple to place them in user.config, for example by using the *.settings file designer to make a user setting called “Password” and doing the following in code...

Properties.Settings.Default.Password = Convert.ToBase64String(securePassword.GetProtectedData());

...and to reverse it...

string encPassword = Properties.Settings.Default.Password;
if (!string.IsNullOrEmpty(encPassword))
{
SecureString passwordString = new SecureString();
passwordString.AppendProtectedData(Convert.FromBase64String(encPassword));
}

Thanks to pinvoke.net for P/Invoke signatures.