25

所以有一个似乎很少使用的类:SecureString。它至少从 2.0 开始就已经存在,并且有一些 SO 问题,但我想我会问我自己的具体问题:

我有一个登录表单;带有用户名和(屏蔽)密码字段的简单 WinForms 对话框。当用户同时输入并单击“登录”时,信息被传递给一个注入的身份验证类,该类执行一层密钥拉伸,然后对拉伸密钥的一半进行散列以进行验证,而另一半是加密用户的对称密钥账户数据。当这一切都完成后,loginForm 被关闭,身份验证器类被释放,系统继续加载主表单。相当标准的东西,可能比标准的哈希密码和比较涉及更多,但在我的情况下,通过以明文形式存储用户数据,简单的哈希密码将被击败,因为该数据包括第三个的凭据-派对系统(我们都知道人们喜欢重用密码)。

这是第一个问题;我将如何使用 SecureString 从 Password 文本框中检索密码,而不会通过文本框的 Text 属性将其公开为普通 System.String?我假设有一种方法可以访问由 CLR 类包装的文本框的非托管 GDI 窗口,并使用 Marshal 类提取文本数据。我只是不知道如何,我似乎无法找到好的信息。

这是第二个问题;将密码作为 SecureString 后,如何将其从 System.Security.Crypto 命名空间传递给哈希提供程序?我的猜测是我会使用 Marshal.SecureStringToBSTR(),然后从返回的 IntPtr 使用 Marshal.Copy() 回到字节数组中。然后我可以调用 Marshal.ZeroBSTR() 来清理非托管内存,并且一旦我有了哈希值,我就可以使用 Array.Clear() 将托管数组清零。如果有一种更简洁的方法可以让我完全控制内存的任何托管副本的生命周期,请告诉我。

第三个问题;这一切真的有必要吗,或者 System.String 在托管内存环境中固有的不安全性有点夸大其词?任何用于存储密码的东西,无论是加密的还是其他的,都应该在操作系统考虑将应用程序交换到虚拟内存之前(允许在硬关机)。冷启动攻击是一种理论上的可能性,但实际上,这有多普遍?更大的担忧是现在解密的用户数据,它作为用户的一部分在整个应用程序生命周期内一直存在(因此将成为使用 SecureStrings 的主要候选者,除了它们保持相当休眠的几个基本用法)。

4

2 回答 2

11

如果您认为您需要,SecureString您必须相信攻击者也可以读取您的进程内存。如果后者是真的,他可以在输入密码字符时读取它们,或者直接从文本框内部字符缓冲区读取,或者从屏幕上读取像素。

这是一个不现实的场景。不要使用SecureString. 它帮助不大,而且会浪费你的时间。

冷启动攻击更为真实,但极为罕见。他们需要物理机器访问,通常完全拥有机器。在这种情况下,攻击者阅读是您最不关心的问题。

基本上,您必须设计一个案例,让您的开发人员时间充分利用SecureString.

于 2013-01-22T00:36:05.143 回答
4

首先,我想声明我同意 usr - 不要打扰。

现在到细节:

  • 这个答案为讨论提供了很好的背景。
  • 是一个使用 SecureString 的 TextBox 控件。我没有用过这个,所以我不能评论质量,但是在 MS 博客上,我不认为它是正确的。
  • 要回答有关将数据传递给 System.Security.Crypto 的问题,基本上你不能也没有多少非托管内存编组会帮助你,因为在这种编组过程中,字符串会被解密。它必须这样做,否则它不能被您的目标 API 使用。如果您使用 CSP 或 X509Certificate,则可以使用 SecureSctring,因为框架支持这些,但仅此而已。
于 2013-01-22T00:50:30.580 回答