使用SecureString类
现在既然String靠不住了,我们能有什么简单的方法来特别的保护我的敏感数据吗? 幸运的是, .NET从Version 2.0开始, 为我们提供了一套基于DPAPI的解决方法 - SecureString.
SecureString类具有以下特性:
SecureString中的内容是加密之后的,而不是平文;
使用windows的加密方案DPAPI ;
SecureString只能在基于NT的平台上使用
C#代码示例:
public void MethodA()
{
//using DPAPI to encrpt the sensitive content
System.Security.SecureString password = new System.Security.SecureString();
char[] pass = { 'p', 'a', 's', 's', 'w', 'o', 'r', 'd' };
for (int i = 0; i < pass.Length; i++)
{
password.AppendChar(pass[i]);
}
password.MakeReadOnly();
//pass the encrypted password through memory or file
}
public void MethodB(System.Security.SecureString password)
{
string decryptedPassword = "";
//copy the secure content to a long pointer
IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(password);
try
{
//Convert secure content to string using DPAPI
decryptedPassword = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr);
//using the decrypted password to check
}
finally
{
System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr);
password.Dispose();
}
}
这段代码中有几个值得说明的地方:
代码写得有些粗糙, 仅为示意.
使用Char数组来保存敏感数据的原始值. 因为Char数组的生命周期是可以预期的, 它在超出自己的作用域之后,就被回收.
MakeReadOnly方法, 一旦使用了该方法后, SecureString的内容就不能再被修改,从而保证了加密后的数据不能再被修改,否则将引发异常.
SecureString的解密,是通过将其内容复制到一个长指针中,然后利用DPAPI, 最终获得String.该String不会进入上文所说的那个虚拟Hash Table中.
ZeroFreeBSTR()方法. 因为使用COM Interop引入了非托管资源,所以一定不能忘记使用ZeroFreeBSTR来释放指针,否则会造成内存泄漏.
SecureString类重写了基类的ToString()方法,不过该方法不会返回所持有的加密内容, 而总是返回System.Security.SecureString.