如何避免在 C# 中将 System.String 与 Rfc2898DeriveBytes 一起使用

信息安全 密码 Web应用程序 。网 asp.net 核心
2021-09-05 04:58:07

我正在用 C# 创建一个 .NET 核心 webapp,它接收用户密码并将其散列以存储在服务器上。我正在使用Rfc2898DeriveBytes随机生成的盐。但是,我读过我应该避免在整个过程中使用字符串,因为字符串无法从内存中删除。我知道 .NET 核心有 aPasswordBox将密码保存为 a SecureString,但SecureStrings 无法转换为字节数组以传递给Rfc2898DeriveBytess 的构造函数,而无需大量恶作剧。

由于 webapp 只会在我的服务器上运行,我可以在SecureString它被传递到我的 webapp 后立即将其转换为字符串吗?如果攻击者设法访问服务器的 RAM 以搜索未删除的字符串,那么我可能无法从一开始就保护任何东西。

如果我仍然应该使用 using SecureStrings,散列存储它的最佳做法是什么?

2个回答

.NET Core 团队特别建议不要将SecureString用于新开发。请参阅SecureString文档

我们不建议您将 SecureString 类用于新开发。有关更多信息,请参阅不应在 GitHub 上使用 SecureString。

以及团队在 GitHub 上的推理

动机

  • 的目的SecureString是避免将机密作为纯文本存储在进程内存中。
  • 但是,即使在 Windows 上,SecureString也不作为操作系统概念存在。
    • 它只是使纯文本的窗口更短;它并没有完全阻止它,因为 .NET 仍然必须将字符串转换为纯文本表示形式。
    • 好处是纯文本表示不会作为实例存在System.String- 本机缓冲区的生命周期更短。
  • 除了在 .NET Framework 上,数组的内容是未加密的。
    • 在 .NET Framework 中,内部 char 数组的内容是加密的。由于缺少 API 或密钥管理问题,.NET 并不支持所有环境中的加密。

正确使用 SecureString 很困难,并且可以防止大多数用例不太可能出现的威胁面。正如您所说,如果攻击者可以读取您的内存,那么您还有其他问题。我建议使用普通字符串而不是 SecureString,除非您担心携带液氮的攻击者可以物理访问您的服务器。

如果您真的想使用 SecureStrings,您应该 P/Invoke Windows 加密 API,以便您可以控制内存。我的博客文章Comparing secure strings in .NET中有一个示例。