BCrypt中何时使用2x前缀?

33
问题和标题相同,$2x$ 在 BCrypt 中的作用是什么?
以下情况正确吗?
我们有一组密码,已经使用 $2a$ 前缀哈希化了,在服务器 PHP 版本早于 5.3.7 时。现在我们将 PHP 升级到 5.3.7+,现在我们必须首先使用 $2x$ 算法验证以前的密码,然后重新使用 $2y$ 前缀对密码进行哈希。这正确吗?

1
可以在这个**博客**中找到一个好的答案。但是我不理解这句话的意思:“现在,这段代码假设您在更新服务器之前就发现了问题;如果您在升级后创建了新密码,则需要在$2x$检查失败时检查$2a$哈希值,然后更新为$2y$。”他们的意思是,有时候在PHP 5.3.7-中使用$2a$哈希加密的密码无法与PHP 5.3.7+中的$2x$进行验证。 - msoa
1
另一个答案:CRYPT_BLOWFISH安全修复细节 结果:据我所知,当我们有一组在PHP 5.3.7-上使用$2a$哈希的密码,并想要将PHP更新到5.3.7+时,我们必须在升级后使用$2x$验证旧密码。因此,仅使用$2x$是完全相同的。如果有人认为我犯了错误,请告诉我。谢谢。 - msoa
1个回答

114

BCrypt变体

$2$

BCrypt由OpenBSD团队设计。它旨在为OpenBSD密码文件中存储的密码哈希。哈希密码存储时会使用前缀来标识所使用的算法。BCrypt的前缀是$2$

这与其他算法前缀形成对比:

  • $1$: MD5
  • $3$: NTHASH
  • $5$: SHA-256
  • $6$: SHA-512
  • $7$: scrypt

$2a$

最初的BCrypt规范未定义如何处理非ASCII字符或如何处理空终止符。该规范已进行了修订,以指定在哈希字符串时:

  • 字符串必须采用UTF-8编码
  • 必须包括空终止符

$2x$,$2y$ (2011年6月)

发现了一个crypt_blowfish的漏洞,这是BCrypt的PHP实现。它没有正确处理带有第8位设置的字符。
他们建议系统管理员更新其现有密码数据库,将$2a$替换为$2x$,以指示这些哈希值是错误的(需要使用旧的错误算法)。他们还提出了让crypt_blowfish使用修复后的算法生成的哈希值发出$2y$的想法。包括OpenBSD在内的其他人都没有采用2x/2y的想法。 此版本标记仅适用于crypt_blowfish
版本$2x$$2y$并不比$2a$更好或更强。它们是BCrypt一个特定有缺陷的实现的残留物。 $2b$ (2014年2月) 在OpenBSD实现的BCrypt中发现了一个错误。他们将字符串的长度存储在unsigned char中。如果密码超过255个字符,它将溢出并在255处包装。
BCrypt是为OpenBSD创建的。当他们的库中有错误时,他们决定可以提高版本号。这意味着如果您想保持符合“他们”的规范,其他人也需要跟随。

版本$2b$并不比$2a$更好或更强。它是BCrypt一个特定有缺陷的实现的遗留问题。但由于BCrypt经典地属于OpenBSD,他们可以将版本标记更改为任何他们想要的。

2a2x2y2b之间没有区别。如果您正确编写了实现,它们都会输出相同的结果。

如果一开始就使用utf8存储字符串并对空终止符进行哈希,那么22a2x2y2b之间没有区别。如果你编写的实现正确,它们都会输出相同的结果。
唯一需要关心2x和2y的人是可能在使用crypt_blowfish的人。而唯一需要关心2b的人是可能在运行OpenBSD的人。
所有其他正确的实现都是相同和正确的。

有一件让我感到困惑的事情是,bcrypt 似乎会按设计将输入截断为 72 个字符(或字节?),因此在第一次发生 255 字符环绕时就不应该发生... - user1686
2
它截断为72个字节。通常,您将这些字节作为原始文本的UTF-8编码提供,并包括空终止符。但最终,名义实现会在72个字节后截断;甚至在UTF-8多字节字符中间截断空终止符。但他们并没有人为地限制字符数为71个。从技术上讲,一个“字符”可以占用超过72个字节(例如,“M̡̢̛̖̗̘̙̜̝̞̟̠̀́̂̃̄̅̆̇̉̊̋̌̍̎̏̐̑̒̓̔̕̚”是1个字符,74个字节。“ ”是一个字符,但4个字节)。 - Ian Boyd
2
还有实际存储字符串的现实问题。在良好的编程语言中,string 内部是带有长度前缀和空字符结尾的。而次级的编程语言没有实际的 “string” 类型,所以将其伪装成 CHAR 指针,并可以携带长度信息。此时,他们的字符串类型有误。使用 UInt8 而不是 UInt32 作为长度前缀。如果 C 和 C++ 最终添加了一个“字符串”类型,则所有这些问题都将得到解决。但是由于那些语言维护人员的故意推迟,他们拒绝添加 stringarray - Ian Boyd
挑剔一点:Bcrypt于1997年在OpenBSD 2.1中推出。Ulrich Drepper的sha256crypt和sha512crypt于2007年在glibc 2.7中推出,整整晚了十年。$2$确实被选择作为md5crypt $1$的后继者。然而,Urlich Drepper选择了$5$和$6$,因为$3$已经被选为NTHASH。我不知道他为什么跳过了$4$。 - Aaron Toponce
@AaronToponce 您的历史信息很有用和有趣,但我不知道您指的是什么小错误。您是指我的示例前缀列表中缺少了“$4$”吗? - Ian Boyd
@IanBoyd,你的措辞让人误以为bcrypt选择了$2$,因为$1$、$5$和$6$已经在使用中,而$5$和$6$并不存在。"BCrypt得到了前缀$2$。这与其他算法前缀形成了对比。" - Aaron Toponce

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接