This blog has been moved to Redwerb.com.

Showing posts with label security. Show all posts
Showing posts with label security. Show all posts

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)
Console.WriteLine(str)
ZeroMemory(str, str.Length * 2)
gh.Free()
Console.WriteLine(str)
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)
Next
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.

Monday, October 30, 2006

Protecting Data in .Net

Security is a big issue in computing these days. One way you can protect user's data is by using the DPAPI (Data Protection Application Programming Interface) available on Windows.


The article Managed DPAPI Part I: ProtectedData provides a very good explanation of what this is, so I won't bore you with the details here, but I will provide you with a code sample that you can use. To use this code sample, simply create a C# console application in VS.Net 2005 and paste this into the main file (I believe it will be called Program.cs).


One thing that should be mentioned, this does not protect the data in memory. It can be used to protect data that is written out to disk, but an industrious hacker can get the sensitive information out of memory. Check out Managed DPAPI Part II: ProtectedMemory for more information on protecting data while it is in memory.



using System;
using System.Security.Cryptography; // reference assembly System.Security.dll
using System.Text;

namespace DPAPIExample
{
class Program
{
static void Main(string[] args)
{
string test = "hello world";
string encryptedValue;
string decryptedValue;

Console.WriteLine(test);
encryptedValue = Encrypt(test);
Console.WriteLine(encryptedValue);
decryptedValue = Decrypt(encryptedValue);
Console.WriteLine(decryptedValue);
Console.ReadKey();
}

// This is an article on using the ProtectedData API (a wrapper around DPAPI)
// http://blogs.msdn.com/shawnfa/archive/2004/05/05/126825.aspx
private static byte[] sEntropy = System.Text.Encoding.Unicode.GetBytes("put whatever you want here");

public static string Encrypt(string text)
{
Byte[] data = Encoding.Unicode.GetBytes(text);
Byte[] protectedData = ProtectedData.Protect(data, sEntropy, DataProtectionScope.CurrentUser);
return Convert.ToBase64String(protectedData);
}

public static string Decrypt(string encryptedText)
{
Byte[] protectedData = Convert.FromBase64String(encryptedText);
Byte[] data = ProtectedData.Unprotect(protectedData, sEntropy, DataProtectionScope.CurrentUser);
string text = Encoding.Unicode.GetString(data);
return text;
}
}
}