Wednesday, October 21, 2009

Safely using a SecureString in C# (don't convert it to a String)

There are a ton of examples online about how to use a C# SecureString object, but most of them have 1 key bug in them that renders the use of SecureString redundant - the examples convert the SecureString into a System.String object!

For those who don't know what a SecureString is, it's secure, it's safe and it should be used to protect resources like passwords, secret keys, etc. After some digging, I found a way to reduce the SecureString attack surface as much as possible. Here's how to generate an RFC-2104 compliant signature (used by AWS services like S3) with a SecureString:
public static string Sign(string data, System.Security.SecureString key, KeyedHashAlgorithm algorithm)
{
    // pointer to hold unmanaged reference to SecureString instance
    IntPtr bstr = IntPtr.Zero;
    char[] charArray = new char[key.Length];
    try 
    {   
        // Marshal SecureString into byte array
        bstr = Marshal.SecureStringToBSTR(key);
        Marshal.Copy(bstr, charArray, 0, charArray.Length);
        algorithm.Key = Encoding.UTF8.GetBytes(charArray);
        return Convert.ToBase64String(algorithm.ComputeHash(
            Encoding.UTF8.GetBytes(data.ToCharArray()))
            );  
    }   
    finally
    {   
        // Make sure that the clear text data is zeroed out 
        algorithm.Clear();
        Array.Clear(charArray, 0, charArray.Length);
        Marshal.ZeroFreeBSTR(bstr);
    }   
}

No comments:

Post a Comment