哪种密码存储方法更安全



哪种是更安全的密码存储方法? 我缺乏数学背景来自己确定答案。

为了论证起见,让我们假设为以下每种方法生成的所有密码和用户名都是随机生成的 6 个字符,已知正好是六个字母-肱骨-特殊字符字段,并且每个字段使用相同的哈希算法和相同的传递次数。

  1. 标准方式。用户名以纯文本形式存储,并且仅要发现密码。哈希(明文密码 + 唯一记录盐) = 存储在数据库中的密码。

  2. 一个识别为 LoginInfo = Hash(加密(用户名、密码)+ 共享盐)的字段。用户名和密码都不会以任何其他格式存储。

用户名/密码组合的强制交叉尝试是否抵消了共享盐的弱点,而不是唯一的记录盐?当然,这完全忽略了对可用性的所有影响,完全关注安全性。

谁能指出我使用任何软件来帮助我自己回答这个问题,因为我缺乏密码学和数学知识来自己得出答案?

请随时将其移至更合适的论坛。 我不知道还能把它放在哪里。 但是,我不认为这是一个与程序员日常工作无关的话题。

请阅读如何安全地散列密码? 总结一下:

  • 切勿使用任何哈希算法的单次传递。
  • 永远不要自己滚动,这就是您的示例 2(示例 1 也是如此,如果 + 表示串联)。
  • 用户名以明文形式存储
  • 每个用户生成的盐,8-16 个随机字节,以明文形式存储
    • 纯二进制或编码为 Base64 或十六进制或任何您喜欢的内容。
  • 使用 BCrypt、SCrypt 或 PBKDF2
    • 至少在密码哈希竞赛结果之后的一段时间。
  • 使用尽可能高的工作因子/成本/迭代计数,因为您的 CPU 在预期的未来高峰时段可以处理
  • 特别是对于 PBKDF2,不要要求比本机哈希产生的更多的二进制输出字节。 无论如何,我会说不少于20个二进制字节。
    • SHA-1:输出 = 20 字节(40 个十六进制数字)
    • SHA-224:20 字节 <= 输出 <= 28 字节(56 个十六进制数字)
    • SHA-256:20 字节 <= 输出 <= 32 字节(64 个十六进制数字)
    • SHA-384:20 字节 <= 输出 <= 48 字节(96 个十六进制数字)
    • SHA-512:20 字节 <= 输出 <= 64 字节(128 个十六进制数字)
  • 特别是对于PBKDF2,SHA-384和SHA-512目前在64位系统上具有比较优势,因为2014年老式GPU的许多攻击者将使用64位操作比防御CPU比32位操作具有更小的优势。

如果你想要一个示例,那么也许可以看看PHP源代码,特别是password_hash()和password_verify()函数,根据 PHP.net 密码哈希常见问题解答。

或者,我的github存储库中有各种(目前非常粗糙的)密码哈希示例。 现在它几乎完全是PBKDF2,但我将来会添加BCrypt,SCrypt等。

正如您所说,选项 1 是存储密码的标准方法。只要您使用安全的哈希函数(例如。NIST推荐PBKDF2)使用独特的盐,您的密码是安全的。所以我会推荐这个选项。

选项 2 实际上没有意义。您无法"撤消"哈希函数,那么为什么要加密其内容呢?然后,您还必须将加密密钥存储在完全不同的地方,这是完全不同的问题。

另外,共享盐是什么意思?如果您总是使用相同的盐,那么这就会破坏对哈希进行盐处理的意义。每行独特的盐是要走的路。

我会说将用户名和密码合并到单个哈希中会使事情过于复杂,并限制了您在开发中的选择,因为您无法从给定用户名的数据库中获取一行。

假设您想在 5 次错误密码尝试后锁定用户。使用标准的纯文本用户名和散列 pw,您只需有一个"login_attempt_count"列,并在每次错误输入密码时更新该用户的行。

如果您的用户名和密码是一起散列的,则无法确定使用登录尝试计数更新哪一行,因为具有错误密码的散列正确用户名与任何哈希都不匹配。我想你可以有某种映射功能来获得给定用户名的row_id,但我会说它只是不必要的复杂,而且随着更大的复杂性,你更有可能出现安全漏洞。

正如我所说,我只选择选项1。这是存储密码的行业标准方式,对于几乎任何应用程序来说都足够安全(只要您使用现代安全哈希函数)。

相关内容

  • 没有找到相关文章

最新更新