Bcrypt 加密与校验
在浏览器里生成和校验 bcrypt 哈希:可选 $2b$、$2y$、$2a$ 前缀与 4–31 的成本,提示 72 字节上限,并说明 PHP、Laravel、Node.js、Go、Spring 能否识别。密码不上传。
- 在浏览器中处理
- 数据不离开你的设备
- 免费 · 无需注册
用微信扫描以下二维码即可分享
示例、说明与常见问题 带实际输出的示例、与同类工具的差别,以及常见问题。
实例:重置若依(RuoYi)的管理员密码
若依前后端分离版(RuoYi-Vue)用 Spring Security 的 BCryptPasswordEncoder 加密密码(SecurityUtils.encryptPassword)。初始化脚本 sql/ry_20260417.sql 里,admin 和 ry 两个账号的 password 字段都是下面这个值,README 写明演示账号是 admin / admin123。把它粘贴到「校验」页,输入 admin123,结果是「匹配」:
$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2
上线前要换掉这个默认密码时,在「生成」页输入新密码,前缀选 $2a$、成本选 10(和若依自己生成的一致),把结果写回数据库:
UPDATE sys_user SET password = '把生成的哈希粘贴在这里' WHERE user_name = 'admin';
改完再用「校验」页核对一次新密码和哈希,确认没有复制漏字符。
实例:粘贴来的值不是标准格式
从不同地方复制出来的哈希常常带着「外壳」。Spring Security 的 DelegatingPasswordEncoder 会在前面加 {bcrypt};Spring Security 7.1.1 用 PasswordEncoderFactories.createDelegatingPasswordEncoder() 生成的一个值如下(密码 Ruoyi@2026),本页会去掉 {bcrypt} 再校验:
{bcrypt}$2a$10$Syj8x8XixpYEkWocxvjgbuqT3xOMxpG.utD30HGZwQBzRMIxVnroC
同样会处理的还有:前后的引号和空格、htpasswd 行开头的 用户名:、Docker Compose 里写成 $$ 的美元符号、Django 的 bcrypt$ 与 bcrypt_sha256$(后者先对密码做 SHA-256)。哈希本身坏了时会指出位置,例如少了最后一个字符会提示「应有 60 个字符,这里只有 59 个」:
$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu
选哪个前缀
对 UTF-8 密码来说,$2a$、$2b$、$2y$ 的算法相同:$2y$ 标记修复 CVE-2011-2483 之后的 crypt_blowfish 结果,$2b$ 是 OpenBSD 2014 年改用的标记,crypt_blowfish 1.3 对 $2b$ 的处理与 $2y$「完全相同」(Openwall)。真正的差别在于各个库认不认。2026-10-02 我们用同一批哈希逐个测试:
| 库 | 版本 | $2a$ | $2b$ | $2y$ | 超过 72 字节时生成 | 默认写出 |
|---|---|---|---|---|---|---|
PHP password_verify | 8.4.26 | ✓ | ✓ | ✓ | ✂ 截断 | $2y$12$ |
Laravel Hash::check | 13.34.0 | ⚠ 抛异常 | ⚠ 抛异常 | ✓ | ✂ 截断 | $2y$12$ |
Python bcrypt | 5.0.0 | ✓ | ✓ | ✓ | ✗ 报错 | $2b$12$ |
Python bcrypt | 4.2.0 | ✓ | ✓ | ✓ | ✂ 截断 | $2b$12$ |
Node.js bcrypt | 6.0.0 | ✓ | ✓ | ✗ false | ✂ 截断 | $2b$10$ |
Node.js bcryptjs | 3.0.3 | ✓ | ✓ | ✓ | ✂ 截断 | $2b$10$ |
Go x/crypto/bcrypt | 0.57.0 | ✓ | ✓ | ✓ | ✗ 报错 | $2a$10$ |
| Spring Security | 7.1.1 | ✓ | ✓ | ✓ | ✗ 报错 | $2a$10$ |
| Spring Security | 6.5.11 | ✓ | ✓ | ✓ | ✗ 报错 | $2a$10$ |
| Symfony | 8.1.0 | ✓ | ✓ | ✓ | 先做 SHA-512 | $2y$13$ |
Laravel 的框架配置默认 HASH_VERIFY 为 true,PHP 的 password_get_info() 只把 $2y$ 认作 bcrypt,所以 $2a$、$2b$ 会抛 This password does not use the Bcrypt algorithm.。结论:给 PHP / Laravel 用 $2y$,给 Node.js 用 $2b$,Java、Go、Python 三种都行。只改前缀,哈希依然有效,「校验」页会直接列出另外两种写法。
72 字节与中文密码
bcrypt 最多读密码的前 72 个字节。UTF-8 里一个汉字通常占 3 个字节,所以 24 个汉字就到上限:
我家的猫叫小橘子它今年三岁了最喜欢在阳台上晒太阳
这句正好 72 字节,再多一个字就不起作用。超过上限时各库的做法不同:PHP、Node.js bcrypt、bcryptjs 悄悄截断;Python bcrypt 5、Go、Spring Security 6.3 及以上直接报错(我们测到 6.2.8 仍截断)。本页会提示最后一个被计入的字,并在校验结果里注明「只比较了前 72 字节」。
成本怎么选
成本是 2 的指数:成本 12 做 212 = 4,096 轮密钥设置,比成本 11 慢一倍。OWASP 密码存储速查表要求至少 10,并把 bcrypt 定为「只在没有 Argon2 和 scrypt 的旧系统里使用」;新项目优先 Argon2id。本页显示的耗时是浏览器里 JavaScript 实现的速度,服务器上的原生库通常更快,最终以登录服务器上的实测为准。
与其他在线工具的区别
2026-10-02 用同一组输入测试了 cn.bing.com 搜「bcrypt 在线」排在前面的 xyutil.com 和 33tool.com:两者都在浏览器里计算,只生成 $2a$;73 字节的密码对比前 72 字节的哈希,两者都显示匹配且不提示;含 ! 的哈希两者都只说「不匹配」,不指出格式错误。本页可选前缀,并说明不匹配的具体原因。
限制
- 计算用 bcryptjs 2.4.3。成本最高可选 31,但在浏览器里要算几天,可随时点「取消」。
$2x$(旧 crypt_blowfish 缺陷产生的哈希)只在密码全是 ASCII 时按$2a$校验。- 密码按输入的字符原样转成 UTF-8,不做 Unicode 规范化。
- 只支持 bcrypt,Argon2、scrypt、SHA-crypt 等会被识别出名称但不校验。生成 Apache / Nginx 用的文件请用 htpasswd 生成器,生成随机密码请用密码生成器。
FAQ
bcrypt 能解密吗?
不能。bcrypt 是单向哈希,没有密钥,也没有反向运算。所谓校验,是用同一个盐和成本把你输入的密码再算一遍,看结果是否相同。忘了原密码只能重置:生成新哈希写回数据库。
Spring Boot 项目该选哪个前缀?
Spring Security 的 BCryptPasswordEncoder 默认写 $2a$,读取时 $2a$、$2b$、$2y$ 都认(6.5.11 与 7.1.1 实测),所以选哪个都能登录。要和 Spring 自己生成的值保持一致,就选 $2a$。
同一个密码每次生成的哈希都不一样,正常吗?
正常。每次都会随机生成 16 字节的盐,盐写在哈希的第 8–29 个字符里。校验时从哈希里取出盐再计算,所以任何一个结果都能通过校验。
成本选多少合适?
OWASP 要求至少 10。PHP 8.4、Laravel、Python 默认 12,Node.js bcrypt、Go、Spring Security 默认 10。在实际负责登录的服务器上计时,选能在远低于 1 秒内算完的最高值。
密码会被上传吗?
不会。计算在当前标签页的 Web Worker 里进行,页面不发送密码或哈希,也不保存;本页不加载统计和广告。