Python bcrypt中'$2a$'的意义是什么?

4 投票
1 回答
2334 浏览
提问于 2025-04-17 19:40

在网上和StackOverflow上有一些资料可以找到,但它们似乎有些矛盾,也不够完整。

所以我想问的是:

在python-bcrypt中,前面加上的$2a$有什么重要意义?

我具体使用的是这个实现:http://www.mindrot.org/projects/py-bcrypt/,但这个问题是普遍适用的。

另外,能否说明一下在python-bcrypt模块中,这个设置是否可以配置?还有是否真的存在安全问题,导致你需要使用某个特定的不同实现。

1 个回答

5

$2a$ 是用来表示所使用的算法的标识符。

在 OpenBSD 的密码文件中,有一些标准用于存储密码。每个密码前面都有一个 算法标识符

  • $1$: MD5 哈希
  • $2$: bcrypt 哈希
  • $5$: SHA2-256 哈希
  • $6$: SHA2-512 哈希

BCrypt 变种

当 bcrypt 最初发布时,它的标识符是 $2$

$2$

BCrypt 是由 OpenBSD 的团队设计的,目的是为了在 OpenBSD 的密码文件中存储密码的哈希值。哈希后的密码会加上一个前缀,以便识别所使用的算法。BCrypt 的前缀是 $2$

$2a$

最初的 BCrypt 规范没有定义如何处理非 ASCII 字符,也没有说明如何处理空字符终止符。后来规范进行了修订,明确规定在哈希字符串时:

  • 字符串必须是 UTF-8 编码
  • 必须包含空字符终止符

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

发现了一个 bug,在 crypt_blowfish 中,这是一个 PHP 实现的 BCrypt。它错误地处理了第 8 位被设置的字符。

建议系统管理员更新他们现有的密码数据库,将 $2a$ 替换为 $2x$,以表示这些哈希是有问题的(需要使用旧的有缺陷的算法)。他们还建议 crypt_blowfish 对修复后的算法生成的哈希使用 $2y$。但包括 OpenBSD 在内的其他人并没有采纳 2x/2y 的想法。这个版本标记仅限于 crypt_blowfish

版本 $2x$$2y$ 并不是比 $2a$ “更好”或“更强”。它们只是某个特定有缺陷的 BCrypt 实现的遗留物。

$2b$ (2014年2月)

在 OpenBSD 的 BCrypt 实现中发现了一个 bug。他们将字符串的长度存储在一个 unsigned char 中。如果密码超过 255 个字符,就会溢出并在 255 处回绕。

BCrypt 是为 OpenBSD 创建的。当他们的库出现 bug 时,他们决定可以更新版本。这意味着如果你想跟上“他们”的规范,其他人也需要这样做。

版本 $2b$ 并不是比 $2a$ “更好”或“更强”。它只是某个特定有缺陷的 BCrypt 实现的遗留物。但由于 BCrypt 正式归 OpenBSD 所有,他们可以随意更改版本标记。

2a2x2y2b 之间没有区别。如果你的实现是正确的,它们的输出结果都是一样的。

如果你从一开始就做对了(以 utf8 存储字符串并且哈希空字符终止符),那么:22a2x2y2b 之间没有区别。如果你的实现是正确的,它们的输出结果都是一样的。

只有那些可能使用过 crypt_blowfish 的人需要关心 2x2y。而只有那些可能在运行 OpenBSD 的人需要关心 2b

其他所有正确的实现都是相同且正确的。

撰写回答