This blog has been moved to

Friday, November 17, 2006

Securing Text Data

Perhaps it's just me, but trying to figure out how to secure text data is confusing. Based on all of the articles available, if you are creating an application that uses passwords or other sensitive information, you should use a SecureString, that much is clear. However, a SecureString isn't very useful since it is encrypted (you can't compare a SecureString against a database value, pass it to your credit card processing, etc).

After many hours of research, I was able to find a single example of how to secure text in an MSDN article (of course, it's only mentioned in passing). How to encrypt and decrypt a file by using Visual Basic .NET or Visual Basic 2005 contains a reference to the ZeroMemory API that allows you to clear a string from memory and GCHandle to make sure you don't end up with a bunch of copies of the string.

The following code will create a string, pin it in memory using GCHandle (to make sure it doesn't get moved or have multiple copies made), then destroy the contents of the string so that it can't be held in memory.

    Sub Main()
Dim str As String = "HI"
Dim gh As GCHandle = GCHandle.Alloc(str)
ZeroMemory(str, str.Length * 2)
End Sub

Private Declare Sub ZeroMemory Lib "kernel32.dll" _
Alias "RtlZeroMemory" _
(ByVal Destination As String, _
ByVal Length As Integer)

The idea behind this is to leave the text in memory for a very short period of time to make it very difficult for a hacker to get. The sensitive text can be stored in a SecureString until you are ready to use it.

Before I found the ZeroMemory solution, I had written another one that I'm going to post here just because it seems interesting. Basically, I use reflection to call a method on System.String that is intended to be used by StringBuilder that will replace a char without making a copy of the string (typically Strings are immutable, any changes to it result in a copy of the string).

    Public Shared Sub DestroyString(ByVal str As String)
Dim mi As MethodInfo
mi = GetType(String).GetMethod( _
"ReplaceCharInPlace", _
BindingFlags.NonPublic _
Or BindingFlags.Instance)

For i As Integer = 0 To str.Length - 1
Dim ch As Char = str(i)
Dim args() As Object
args = New Object() {ch, ChrW(0), i, 1, 0}
mi.Invoke(str, args)
End Sub

I am currently working on another article for Code Project on securing text data, complete with a PasswordBox WinForm control, SecurePassword class, and more. Once it is available, I will post a link to it here.

No comments: