技术开发 频道

.NET : 如何保护内存中的敏感数据?

  使用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.

0
相关文章