Bcrypt哈希校验

生成哈希
Bcrypt 是专门为口令存储设计的慢哈希,自带随机盐与代价因子,同一个密码每次生成的结果都不同, 校验时必须使用完整的 60 字符哈希串。它不可逆,无法从哈希值还原出密码。
生成结果
输入密码与参数后点击「生成哈希」

校验哈希

待校验的密码与哈希值
校验结果
粘贴已存储的哈希值,再输入密码进行校验
Bcrypt 的哈希串自带算法版本、代价因子与盐值,所以校验时不需要再填写任何参数, 直接粘贴完整哈希串即可。
校验只会在本机完成,密码与哈希值都不会发送到服务器。
哈希串里的 $2a$ / $2b$ 是 Bcrypt 的版本前缀, 10 是代价因子(210 = 1024 轮)。
在线生成与校验 Bcrypt 密码哈希,可调代价因子 cost(4–15)、支持自定义 16 字节盐值,输出标准 $2a$ 编码串;校验时粘贴哈希串与密码即可验证是否匹配。全部在本机浏览器完成,密码不上传服务器。

这个工具能做什么

Bcrypt 密码哈希生成与校验工具,分为两个面板:

  • 生成哈希:输入明文密码,选择代价因子(cost)与盐值,生成标准的 Bcrypt 编码串,形如 $2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy。
  • 校验哈希:粘贴已存储的 Bcrypt 哈希串,再输入待验证的密码,工具会告诉你是否匹配。

所有计算都在浏览器本机完成,密码与哈希值都不会上传到服务器。

使用步骤

  1. 在「生成哈希」面板输入明文密码(可点右侧眼睛图标切换显示)。
  2. 设置代价因子。默认 10,是绝大多数系统的通用选择;安全要求高可调到 12。
  3. 盐值保持「随机 16 字节」即可,工具会为每次生成都取新的随机盐。需要复现某次结果时切到「自定义文本」。
  4. 点击「生成哈希」,结果区给出完整编码串,并附带盐值的十六进制与 Base64 形式。
  5. 要验证时,把哈希串与密码填到下方「校验哈希」面板,点「校验」。

Bcrypt 是什么

Bcrypt 由 Niels Provos 和 David Mazières 于 1999 年基于 Blowfish 分组密码设计,最初用于 OpenBSD,如今是应用最广的口令哈希算法之一。

项目说明
设计者Niels Provos、David Mazières(1999)
基础算法Blowfish(EksBlowfish 变体)
输出长度固定 60 个字符的编码串
盐长度固定 16 字节(编码后 22 个 Base64 字符)
摘要长度23 字节(编码后 31 个字符)
代价因子cost,取值范围 4 – 31,实际常用 10 – 14
是否可逆不可逆

编码串的结构

以 $2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy 为例:

片段含义
$2a$算法版本标识
10代价因子,实际轮数为 2^10 = 1024
N9qo8uLOickgx2ZMRZoMye22 个 Base64 字符,表示 16 字节盐值
IjZAgcfl7p92ldGxad68LJZdL17lhWy31 个 Base64 字符,表示 23 字节摘要

版本前缀的区别

前缀说明
$2$最早的版本,存在已知缺陷,已基本淘汰
$2a$修正了长度处理问题,目前最常见
$2b$OpenBSD 修正了一个 72 字节边界处的溢出缺陷,新实现多输出此版本
$2x$ / $2y$历史遗留(PHP 早期实现与 crypt_blowfish 的兼容标记),现代系统一般不再输出

本工具使用 hash-wasm 的实现,输出 $2a$ 前缀,可以校验 $2a$ / $2b$ / $2y$ 等各版本哈希串。

代价因子怎么选

cost 每 +1,计算量翻倍。下表为浏览器本机(WebAssembly)实测的参考耗时:

cost轮数参考耗时建议
8256约 20 ms仅用于测试,强度偏低
101024约 70 ms默认推荐,兼顾安全与体验
124096约 260 ms安全要求较高时使用
1416384约 1 s高安全场景,登录会明显变慢
16 及以上65536+数秒以上一般不建议,容易造成拒绝服务

原则:让一次校验耗时落在 100 – 500 毫秒之间。这样正常登录用户几乎无感,而攻击者尝试一次的成本被抬高到无法承受。

⚠️ 72 字节限制

Bcrypt 只处理密码的前 72 个字节,超出的部分会被静默忽略:

  • 72 字节不等于 72 个字符。UTF-8 编码下,一个汉字占 3 字节,所以 24 个汉字就会被截断。
  • 后果:超长密码的后半段不参与计算,两个前 72 字节相同的密码会被判定为同一个。
  • 规避方法:先用 SHA-256 处理密码再交给 Bcrypt(即「预哈希」),但要注意这会引入 null 字节截断问题,需要做 Base64 或十六进制编码后再传入。更简单的做法是限制密码最大长度并提示用户。

Bcrypt 与 Argon2 怎么选

维度BcryptArgon2
发布年份19992015
抗 GPU 能力一般(只消耗 CPU 时间,不消耗内存)强(内存开销可调)
参数维度只有 cost内存 m、迭代 t、并行 p 三个维度
兼容性极好,几乎所有语言与框架内置较好,现代语言多数支持,部分旧环境缺失
推荐度存量系统首选、新项目可用新项目的首选

OWASP 密码存储备忘单的立场是:优先 Argon2id,其次 scrypt,再次 Bcrypt,最后 PBKDF2。但如果现有系统已经用了 Bcrypt 且 cost 设置合理,没有必须迁移的理由。

常见误区

  • 哈希值每次都不一样,是不是坏了? 不是。Bcrypt 每次生成都会取新的随机盐,所以同一个密码两次生成的哈希串不同。校验时必须用完整的哈希串,而不是重新生成一个来比较。
  • 可以拿哈希串的某一段来比较吗? 不可以。校验必须用算法提供的验证函数(本工具的「校验哈希」面板)重新计算,不能简单地字符串比较。
  • Bcrypt 是加密吗? 不是,它是单向哈希,无法从哈希串还原出密码。
  • cost 越大越安全,所以设成 20 最好。 代价因子过大会让每次登录耗费数秒,攻击者可以借此发起拒绝服务攻击(用大量错误密码把服务器 CPU 打满)。应按业务机器的实际算力选择。

常见问题 FAQ

为什么要给密码加盐?

不加盐时,相同密码会产生相同哈希,攻击者可以用一张预先算好的「哈希→明文」对照表(彩虹表)批量反查。加盐让每个密码的哈希都不同,彩虹表失效,攻击者只能对每个密码单独暴力破解。

Bcrypt 可以用来加密文件吗?

不可以。Bcrypt 是为口令设计的慢哈希,输出固定 60 字符,不能加密数据也不能解密。加密文件请使用 AES 等对称加密算法。

同一个哈希串在不同语言里校验结果会不一样吗?

只要实现遵循同一标准就不会。需要注意版本前缀差异($2a$ / $2b$ / $2y$)与 Base64 变体表的差异。本工具基于 hash-wasm 实现,与 PHP password_hash、Node bcryptjs 等主流实现结果一致。

密码和哈希值会被上传到服务器吗?

不会。生成与校验全部通过浏览器本地的 WebAssembly 完成,页面不发送任何包含密码或哈希值的请求。可以在开发者工具的 Network 面板确认。

校验时为什么不需要再填盐值和 cost?

因为 Bcrypt 的编码串自带算法版本、代价因子与盐值,校验函数可以直接从串里解析出来。这也是 Bcrypt 比 PBKDF2 更方便的地方——PBKDF2 的输出是裸摘要,校验时必须额外提供参数。

Bcrypt 和 Argon2 该选哪个?

新项目优先 Argon2id,它能通过内存开销抵抗 GPU 与 ASIC 破解,参数维度更多。Bcrypt 的优势是兼容性极好、几乎所有语言框架都内置,适合存量系统。OWASP 的推荐顺序是 Argon2id > scrypt > Bcrypt > PBKDF2。

Bcrypt 能解密吗?

不能。Bcrypt 是单向哈希,没有解密过程。所谓「验证」是把待测密码用哈希串里记录的盐值与代价因子重新计算一遍,再比较结果是否一致,而不是还原原密码。

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

它们是 Bcrypt 的版本前缀。$2$ 是最早版本,有已知缺陷;$2a$ 修正了长度处理问题,最常见;$2b$ 修复了 72 字节边界的溢出缺陷,新实现多输出它;$2x$/$2y$ 是 PHP 与 crypt_blowfish 的历史兼容标记。本工具输出 $2a$,可校验各版本哈希串。

Bcrypt 的 72 字节限制是什么?

Bcrypt 只使用密码的前 72 个字节,超出部分会被静默忽略。注意是字节不是字符:UTF-8 下一个汉字占 3 字节,所以 24 个汉字就会被截断。建议在业务层限制密码最大长度,或先做 Base64 编码的预哈希。

代价因子 cost 应该设多少?

原则是让一次校验耗时落在 100 – 500 毫秒。通用推荐 10(约 70 ms);安全要求高可用 12(约 260 ms)。不建议超过 14,过慢会让登录变卡,还可能被用来发起拒绝服务攻击。

Bcrypt 的哈希值为什么每次都不一样?

因为每次生成都会取新的随机 16 字节盐值。盐值会写在哈希串里,所以校验时仍然能正确匹配。这是正常且必要的行为,可以防止彩虹表攻击和「相同密码产生相同哈希」的信息泄露。

Bcrypt 是什么?

Bcrypt 是 Niels Provos 和 David Mazières 于 1999 年基于 Blowfish 分组密码设计的口令哈希算法,最初用于 OpenBSD。它内置随机盐与可调代价因子,输出固定的 60 字符编码串,是应用最广的口令哈希算法之一。