哈希密码的最佳实践

Posted

技术标签:

【中文标题】哈希密码的最佳实践【英文标题】:Best practice of Hashing passwords 【发布时间】:2013-12-09 18:46:53 【问题描述】:

我想知道使用哪种方法将密码存储在数据库中。我已经使用 MD5 实现了它,但根据一些帖子 SHA1 更安全。还有其他更安全的方法吗? 请帮我找出保护密码的最佳方法。

【问题讨论】:

***.com/a/1592620/1336590 因为它说“这些方法是单向哈希。您将无法找回用户丢失的密码。他们只能重置密码。”但我想知道我可以使用哪种方法,因为我也想检索密码功能.. @user1650891 我建议阅读我的回答中的主题,我会尝试扩展该主题。 @user1650891 - 我试图回答 similar question 。最重要的是,您切换到慢速密钥派生函数,如 BCrypt 或 PBKDF2。 This 是一本好书。 【参考方案1】:

当然 SHA1 比 MD5 更安全,但在大多数情况下它还不够安全。

您可能会发现视频 How NOT to Store Passwords by Computerphile 很有用 - 时长 9 分 24 秒。

您必须意识到,在身份验证和访问控制方面有很多内容需要涵盖,因此只有一个好的散列方案是不够的。


关于存储密码。

如您所知,您不存储密码。实际上,在存储密码时,一般来说,您希望使用为此目的优化的现代算法来存储密码的加盐哈希。对于盐,可以将其与散列一起存储,对于盐值尽可能使用随机值。

注意:出于安全目的生成随机值时,请使用加密安全生成器(例如 RandomNumberGenerator for .NET - example 的子类)。这个随机数生成器被设计成难以预测。虽然标准随机数生成器是可重复的(即使用System.Random,您只需要生成所有值的种子,而猜测种子所需要的只是使用相同种子生成的足够连续值)。

另请注意:大多数哈希都经过优化以快速计算,MD5 和 SHA1 都属于该类别。 您应该选择一个不那么快的,以便在尝试破解您的密码时,攻击将花费合理的时间来计算哈希值。

这样的算法之一是 BCrypt - 其他包括 Scrypt 和 PBKDF2 - 在使用 C# 中的 BCrypt 时,您会发现使用 BCrypt to Hash Your Passwords: Example for C# and SQL Server 的文章很有用。如果您无法使用 BCrypt 或类似算法,您至少应该使用 SHA2 的变体(SHA256、SHA512 等)。

附录:您可以使用 BLC 中可用的类HMACSHA256 作为密钥派生函数,将您的盐作为密钥传递。这比附加或前置盐(可能落到Length extension attacks)更可取。也就是说,如果您使用 HMAC,并且您的哈希算法容易受到长度扩展攻击(已知或将被发现),那么您的系统是安全的。 MD5、SHA1 和 SHA2 一样容易受到这种攻击。 SHA3​​ 不是。遗憾的是 SHA3 不包含在 BLC 中(不,它不是 SHA384),您可以从 Multiformats.HashHashLib 获取它。我不得不提一下,SHA3 也被设计成在硬件中实现时速度很快。请记住,对于密码来说,使用慢速哈希会更好


附录:Argon2

作为it was pointed a year ago,此答案应更新为提及Argon2。我确实在那之前写了原始答案。

当时,我还没有找到我愿意推荐的 C# 实现。由于这个答案引起了我的注意,我又看了看,不再是这样了。

您可以使用Isopoh.Cryptography.Argon2,它具有完全托管的代码(它不是用于 C++ 实现的 C# 绑定,而是完整的 C# 代码),适用于所有主要平台,并且有 Nugets 可用。

注意事项

使用Argon2Version.Nineteen。这是修复已知漏洞的 Argon2 v.1.3 (Nineteen = 0x13)。 使用Argon2Type.DataDependentAddressin (Argon2d),或使用Argon2Type.DataIndependentAddressing (Argon2i) 和TimeCost >= 10。 Argon2d 理论上容易受到侧通道攻击,因此不建议在客户端机器上运行代码。 Isopoh.Cryptography.Argon2 通过使用操作系统调用来防止敏感内存移动到虚拟内存/页面文件/交换并尽快将其归零来缓解这种情况。另一方面,Argon2i 有一个时间-内存权衡漏洞,它允许通过使用更多内存来更快地计算哈希值。论文Towards Practical Attacks on Argon2i and Balloon Hashing 表明,即使在 Argon2 v.1.3 中,您也需要 10 次迭代/遍才能使漏洞利用效率低下。

以下是一些推荐阅读:

Speed Hashing You're Probably Storing Passwords Incorrectly Everything you ever wanted to know about building a secure password reset feature The definitive guide to form based website authentication OWASP's Password Storage Cheat Sheet OWASP's Forgot Password Cheat Sheet

还有视频:Crypto is Back! - Google 技术讲座 - 2009 年 8 月 5 日 - 时长 54 分 32 秒。


关于找回密码。

首先:不要。密码恢复选项的重点不是恢复密码,而是恢复对应用程序的访问。那么...如何恢复对应用程序的访问权限?

很高兴你问。您需要的是另一种验证用户身份的方法。这可能是第二因素身份验证(从安全问题到使用硬件密钥生成器的任何事情)。然而,通常做的是向第三方提供资源,例如邮件。

因此,您想知道用户是否是该用户之前声称拥有的电子邮件(或手机或其他任何东西)的所有者。为此,您向该电子邮件(或其他)发送代码(通常称为令牌或 cookie)。这必须是带有加密安全生成器的随机生成的代码,这样除了该电子邮件的所有者(或其他任何人)之外,其他任何人都无法知道该代码是什么。

现在,如果用户向您的应用程序展示该代码,您几乎确定它是正确的用户。

几乎 因为:电子邮件(或其他)可能已存储在不安全的位置。为了缓解这种情况,您希望对代码(cookie 或令牌)设置时间限制。此外,如果代码已被使用,它应该再次工作。为了获得额外的安全性,您可以向 CAPTCHA 提供资源,以确保此代码不是来自幸运的机器人。

有关此主题的更多信息(此链接也在上面提供):

Everything you ever wanted to know about building a secure password reset feature OWASP's Forgot Password Cheat Sheet

【讨论】:

+1 @Theraot:我编辑了你的帖子以突出计算时间,希望你不介意。 @jgauffin 欢迎您。至于改进答案,我不介意(无论如何,这些答案都在 CC-BY-SA 之下)。 如果不能选择使用第三方代码,则 .Net 框架 2.0 或更高版本中包含 PBKDF2 的实现。它被称为Rfc2898DeriveBytes,是System.Security.Crytography 的一部分。【参考方案2】:

SHA1 的漏洞比 MD5 少。这是一种较新的算法,它使用更多的位并且需要更多的处理才能“破解”。您可以在此处查看大多数主流哈希算法及其已知漏洞:http://en.wikipedia.org/wiki/Cryptographic_hash_function

正如有人已经评论过的,一定要确保在密码哈希中添加“盐”,以进一步掩盖任何可能的模式。

【讨论】:

以上是关于哈希密码的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

指定常量哈希映射时的 Rust 最佳实践 [重复]

在 mysql 中有效存储 md5 哈希的最佳实践

是否有最佳实践/连贯的方法来更新包含哈希键值存储的数据库字段?

一致性哈希(PHP核心技术与最佳实践)

生成重置密码令牌的最佳实践

记住我功能的最佳实践[重复]