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

在C#中,处理密码等敏感数据的正确方法是什么?,c#,security,passwords,securestring,C#,Security,Passwords,Securestring,此应用程序显示一个带有文本框的表单,用户应在其中输入用于解密文档的密码 我有如下代码: string password = passwordTextBox.Text; ... DecryptDocument(password); 但我被告知,从技术上讲,这是一个安全缺陷,因为即使在应用程序关闭后,代表密码的数据也可能保留在内存中 我尝试使用System.Security.SecureString类,但现在我处理的是指向CoTaskMem的指针,这似乎使问题变得更糟: SecureString

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

我有如下代码:

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()函数


是否有办法解决此问题,或者我应该处理此安全漏洞?

如果您真的想使用SecureString,则需要端到端使用它,最好一次只与一个字符交互。每当字符串被解密为字符数组时,您都希望在使用完它后显式清除内存。由此产生的后果:

  • 您应该使用直接与SecureString一起操作的安全文本框控件。请参见一个好例子

  • 您应该修改DecryptDocument以直接获取SecureString

  • 您将希望实现解密,以便它在解密字符上花费的时间尽可能少。NET中的一些加密体系结构实际上直接支持SecureString。如果做不到这一点,最好的办法是使用非托管缓冲区,并在使用完毕后显式清除它


  • “但我被告知,从技术上讲,这是一个安全漏洞,因为即使在应用程序关闭后,代表密码的数据也可能保留在内存中。”——虽然这是事实,但它可能位于内存中的随机位置。你什么都不担心。“有办法解决这个问题吗?还是我应该处理这个安全漏洞?”那会是什么漏洞?就是这个漏洞:@Ramhound,如果你不担心文本在内存中的随机位置,那么就根本不值得使用SecureString。平心而论,它实际上只增加了一小部分安全性;主要关注的是崩溃转储,尽管这些转储可能已经泄露了各种敏感信息(即当前为工作目的而解密的所有信息)。SecureString真正为您带来的唯一好处是降低了泄露密码短语的可能性,这可能会危及密钥(或相关用户访问的其他服务,如果他们重用其密码短语的话)