I've been looking into using the System.Security.SecureString class to hold credit card numbers in memory while they are being processed. Has anyone used the SecureString class for holding credit card numbers, or do most just use the normal System.String class?
I use SecureString for other stuff (not credit cards), if it's going to be cached in memory for an extended time.
The problem I keep encountering is that you still have to marshal it to a normal String in order to actually use it for anything, so it's really limited in its usefulness.
I've created a couple of extension methods to ease working with them a little bit:
public static unsafe SecureString Secure(this string source)
{
if (source == null)
return null;
if (source.Length == 0)
return new SecureString();
fixed (char* pChars = source.ToCharArray())
{
SecureString secured = new SecureString(pChars, source.Length);
return secured;
}
}
public static string Unsecure(this SecureString source)
{
if (source == null)
return null;
IntPtr bstr = Marshal.SecureStringToBSTR(source);
try
{
return Marshal.PtrToStringUni(bstr);
}
finally
{
Marshal.ZeroFreeBSTR(bstr);
}
}
From a PCI-DSS perspective, there is no requirement to protect card numbers stored only in memory.
PCI states only that card numbers persisted to disk, or transmitted across a network must be encrypted. This is a common sense approach to the issue. Using SecureString will ensure that the string is never cached to disk, but as you say - its troublesome to use. This post has some good suggestions though: http://stackoverflow.com/questions/122784/hidden-net-base-class-library-classes#123141
In theory, protecting memory sounds like it would add strength, but in truth if a bad guy has access to the RAM, then its pretty much game over anyway.