在 C# 中,处理敏感数据(如密码)的正确方法是什么

本文关键字:是什么 方法 密码 处理 敏感数据 | 更新日期: 2023-09-27 18:37:25

此应用程序显示一个带有文本框的表单,用户应该在其中输入用于解密文档的密码。

我的代码如下所示:

string password = passwordTextBox.Text;
...
DecryptDocument(password);

但我被告知,从技术上讲,这是一个安全漏洞,因为即使在应用程序关闭后,表示密码的数据也可能保留在内存中。

我尝试使用System.Security.SecureString类,但现在我正在处理指向CoTaskMem的指针,这似乎使问题变得更糟:

SecureString password = new SecureString();
foreach(char i in passwordTextBox.Text.ToCharArray())
password.AppendChar(i);
IntPtr ptr = Marshal.SecureStringToCoTaskMemAnsi(password);
int length = password.Length;
byte[] bytes = new byte[length];
Marshal.Copy(ptr, bytes, 0, length);
DecryptDocument(Encoding.Default.GetString(bytes));
Marshal.FreeCoTaskMem(ptr);

如您所见,看起来我并没有使应用程序更安全,因为迟早我将不得不获取输入(passwordTextBox.Text)并将其转换为可以传递给DecryptDocument()函数的字符串。

有没有办法解决这个问题,或者我应该只处理这个安全漏洞?

在 C# 中,处理敏感数据(如密码)的正确方法是什么

如果你真的想使用SecureString,它需要端到端地使用,最好一次只与一个字符交互。 每当字符串解密为字符数组时,您都需要在使用完内存后显式清除内存。 这样做的后果:

  1. 应使用直接与安全字符串一起操作的安全文本框控件。 请参阅此处以获取一个很好的例子。

  2. 您应该修改解密文档以直接获取安全字符串。

  3. 您需要实现解密,以便它尽可能少地使用解密字符。 .NET 中的某些加密体系结构实际上直接支持安全字符串。 如果做不到这一点,最好的办法是使用非托管缓冲区,并在完成它时显式清除它。