Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

in C#, what is the proper way to handle sensitive data such as a password?

This app displays a form with a textbox where the user is supposed to enter a password used to decrypt a document.

I have code that looks like this:

string password = passwordTextBox.Text;
...
DecryptDocument(password);

But I was told that, technically speaking, this is a security flaw, because the data that represents the password might remain in memory even after the application is closed.

I tried to use the System.Security.SecureString class but now I'm dealing with pointers to CoTaskMem which seems to make the problem worse:

SecureString password = new SecureString();
foreach(char i in passwordTextBox.Text.ToCharArray())
password.AppendChar(i);

IntPtr ptr = Marshal.SecureStringToCoTaskMemAnsi(password);
int length = password.Length;
byte[] bytes = new byte[length];

Marshal.Copy(ptr, bytes, 0, length);

DecryptDocument(Encoding.Default.GetString(bytes));

Marshal.FreeCoTaskMem(ptr);

As you can see, it doesn't look like I'm making the application safer, since sooner or later I will have to take the input (passwordTextBox.Text) and convert it into a string that I can pass to the DecryptDocument() function.

Is there a way to solve this problem or should I just deal with this security vulnerability?

like image 991
John Smith Avatar asked Jun 15 '12 15:06

John Smith


1 Answers

If you really want to use SecureString, it needs to be used end-to-end, preferably only ever interacting one character at a time. Whenever the string is decrypted to a character array, you'll want to explicitly clear out the memory when you're done using it. Consequences of this:

  1. You should use a secure TextBox control that operates with SecureString directly. See here for one good example.

  2. You should modify DecryptDocument to take a SecureString directly.

  3. You'll want to implement the decryption so that it spends as little time with decrypted characters as possible. Some of the crypto architecture in .NET actually supports SecureString directly. Failing that, your best bet is to use the unmanaged buffer and explicitly clear it out when you're done with it.

like image 180
Dan Bryant Avatar answered Nov 15 '22 20:11

Dan Bryant