C#密码散列和验证的参考实现

信息安全 验证 密码 哈希 。网 爪哇
2021-09-04 08:59:45

有没有人有一个参考实现(最好是第 3 方认证,或政府批准)方式单向散列 C# 和/或 Java 的密码?

理想情况下,我希望看到包括此处提到的“盐和胡椒”技术以及任何其他可能适用的现代验证安全技术的东西。

我要保护的内容是用户可以记住的信息,例如密码或挑战问题的答案。

如果您没有完整的代码示例,那么您将选择哪种算法的一般描述以及加盐和加胡椒的示例方法会很有帮助。

3个回答

鉴于您的新“政府批准”要求,我猜一个好的解决方案是RFC 2898中的 PBKDF2 。它是在Rfc2898DeriveBytes Class (System.Security.Cryptography)中为 .NET 实现的。您大概想在那里用 SHA-256 代替 SHA-1。

我也刚刚遇到了相当安全的哈希密码:fshp,它类似于 PBKDF1,但默认使用 SHA-256。它支持可变数量的迭代,默认为 4096。它使用 64 位盐。他们在那里实现了 .NET、Python、Ruby、Perl、PHP5、Java 和 JavaScript。

正如.net impl of bcrypt - Stack Overflow所描述和讨论的那样,对于 .NET/CLR 来说,另一个不错的选择(尽管未经 NIST 批准)似乎是 BCrypt.net:

对于 Java,一个不错的选择是

我想两者似乎都没有“胡椒”概念,也没有 scrypt 的空间复杂性。

基础

基本方法是Hash(secret | salt),它与盐一起存储。显然,使用像 SHA2 变体之一这样的现代哈希算法很重要(尽管目前 SHA1 并没有像 MD5 那样完全被破坏)。请注意,如果您以这种方式存储挑战问题,您可能希望在对其Trim()进行ToLower()散列之前存储秘密。这可能会在一定程度上降低复杂性,但安全问题并不打算像密码那样具有高熵。

像彩虹表这样的蛮力攻击呢?

可以通过两种方式减轻对暴力攻击的担忧:

  1. 要求密钥中的最小熵(长度、复杂性等)。
  2. 增加执行散列所需的计算量。

中使用的方法bcrypt是对标准散列的一个很好的改进,因为它将计算散列的时间增加了许多数量级。基本上,它只是多次迭代地散列秘密: Hash(Hash(...Hash(secret | salt)...))

由于时间量仍然相对较小(数百毫秒),因此不会给合法用户增加无法忍受的延迟。但它可以破坏自动蛮力攻击。

这还不够好

如果 的附加难度bcrypt不足,请尝试scrypt它的工作原理类似bcrypt,但需要将每个迭代哈希保存在内存中,以便在最后进行最终合并。这增加了与时间复杂度相同的时间复杂度,bcrypt但也增加了空间复杂度,使其更难以在硬件中实现,尤其是并行实现。

执行

老实说,我不知道有一个 C# 库来实现这一点,更不用说某个官方机构的“认证”了,但这不会太难。假设您编写线程安全代码,并且密码验证发生在受信任的系统(如服务器)上,则可以最大限度地减少侧信道攻击等实现问题。

进一步阅读:这个答案BCrypt 是一个在 C# 中使用的好的加密算法吗?我在哪里可以找到它?

.Net 答案
根据这篇文章,来自.Net Cryptography命名空间的所有-Cng-CryptoServiceProvider后缀实现都应该经过 FIPS 认证,而不是 -Managed 版本。

缺点:

好处:

  • 它们已通过 FIPS 认证
  • 哈希算法使用 bcrypt