MiServe DevTools

我的贴纸

把工具固定在这里,会保存在此浏览器中。

bcrypt 哈希生成与验证

按你选择的成本用 bcrypt 哈希密码,验证密码与哈希是否匹配,并查看哈希的各个组成部分。

生成密码哈希

成本 10 表示 1,024 轮密钥设置。每加 1,工作量翻倍,对你和对猜密码的人都一样。

bcrypt 哈希

验证密码与哈希

结果

通过 WebAssembly 在浏览器中运行。粘贴的内容不会被上传。

关于此工具

为什么 bcrypt 故意设计得很慢

密码数据库会被盗,拿到数据库的人可以离线猜测密码,速度只受其硬件限制。SHA-256 这样的通用哈希本来就是为速度而设计的,一块显卡每秒就能尝试数十亿个候选值。bcrypt 由 Niels Provos 和 David Mazières 于 1999 年发布,它基于 Blowfish 密码中开销很大的密钥设置过程,并按可配置的次数重复执行,让每一次猜测都代价高昂。

每个哈希还带有自己的 16 字节随机盐值。两个密码相同的用户会得到不同的哈希,针对某个盐值预先算好的表对下一个盐值毫无用处。bcrypt 哈希无法解密,实际可行的攻击是猜测,因此无论成本多高,弱密码仍会很快被猜出。

成本的含义以及如何选择

成本是密钥设置轮数以 2 为底的对数:成本 10 是 1,024 轮,成本 12 是 4,096 轮。每加 1,一次登录以及攻击者的每次猜测所需的时间都会翻倍。成本写在哈希里,所以以后可以提高:旧哈希照样能验证,你可以在密码所有者下次登录时,用新的成本重新计算哈希。

选择你的服务器在登录时能承受的最高成本,且不低于 10,这是 OWASP Password Storage Cheat Sheet 为 bcrypt 给出的最低值。这里显示的耗时是在你浏览器中的 WebAssembly 里测得的,通常比服务器上的原生代码慢,因此请在实际执行哈希的机器上测量。出于这个原因,此工具的成本上限是 14。

72 字节限制

bcrypt 最多只使用密码的 72 个字节。这个限制按字节而不是按字符计算:在 UTF-8 中,é 这样的带重音字母占两个字节,大多数中日韩字符占三个字节,大多数 emoji 占四个或更多字节。许多库会悄无声息地截断更长的输入,这意味着前 72 个字节相同的两个长密码能通过同一个哈希的验证。这里使用的 Go 实现会拒绝对更长的输入计算哈希,出现这种情况时,此工具会提示你。

如果你的用户可能设置更长的密码,最直接的做法是在注册时拒绝,并给出明确的提示。一种常见的变通做法是先用 SHA-256 对密码计算哈希,再把该摘要的 Base64 或 hex 文本交给 bcrypt。绝不能传入原始的摘要字节,因为有些实现读到零字节就会停止。而且 OWASP 速查表不建议这种预哈希,因为它会给一种叫作 password shucking 的攻击留下可乘之机。对于新系统,OWASP 推荐优先使用 Argon2id 而非 bcrypt,而 Argon2id 没有 72 字节限制。

解读哈希,以及此工具的运行方式

bcrypt 哈希共 60 个字符:$2b$ 这样的版本前缀,两位成本和 $,22 个字符的盐值,以及 31 个字符的摘要;盐值和摘要都使用 bcrypt 自己的 Base64 字母表(./A-Za-z0-9)。验证密码所需的一切都在这一个字符串里,所以不需要单独存一列盐值。

哈希和验证由 Go 的 golang.org/x/crypto/bcrypt 包完成,编译为 WebAssembly 后在浏览器的后台线程中运行。密码和哈希不会被发送到任何地方,也不会被保存。本页面适用于测试数据、测试夹具,以及检查你手头已有的哈希:真实用户的密码应由你的应用在你的服务器上进行哈希。

常见问题

为什么同一个密码每次得到的哈希都不一样?

每个哈希都用新的随机盐值生成,而盐值是结果的一部分。验证密码时,bcrypt 会从存储的哈希中读回盐值和成本,再重复一遍计算。所以要用 verify 函数来比较,而不能重新计算哈希后比较字符串。

bcrypt 的成本应该设为多少?

至少用 10;如果服务器上一次登录的耗时仍在你可接受的范围内,就再往上调。每加 1 耗时翻倍,所以请在生产硬件上测量。随着硬件变快,每隔几年重新评估一次这个值。

$2a$、$2b$ 和 $2y$ 有什么区别?

它们标记的是特定实现出现缺陷之后所做的修订:$2y$ 来自 2011 年 crypt_blowfish(PHP 使用的代码)中的修复,$2b$ 来自 2014 年 OpenBSD 中的修复。对于不超过 72 字节的密码,三者生成的摘要相同。此工具写入 $2a$,三者都能验证。

我输入的密码会被发送到服务器吗?

不会。哈希由 WebAssembly 模块在你的设备上计算,此工具不会用你输入的内容发出任何网络请求。两次访问之间不会保存任何内容。

哈希分类的其他工具