bcrypt
bcrypt 是一个常用的密码哈希库,广泛应用于密码保护和身份验证系统中。它的主要功能是通过不可逆的哈希算法将用户密码转换为一个固定长度的散列值,并通过设计确保密码的安全性,即使数据库被攻破,也不会轻易泄露用户的明文密码
# bcrypt 如何保护密码
- 密码哈希化 (不可逆加密)
- 当用户设置密码时,bcrypt 会将明文密码通过哈希算法转换为不可逆的散列值
- 一旦密码被哈希后,即使攻击者获取到哈希值,也无法直接从中还原出明文密码
- 盐值 (Salt)
- 在哈希过程中,bcrypt 会为每个密码生成一个唯一的随机盐值 (Salt)
- 盐值会与密码组合后再进行哈希,确保即使两个用户使用了相同的密码,它们的哈希值也会完全不同,从而防止彩虹表攻击
- 迭代工作因子 (Work Factor)
- bcrypt 使用了可调的工作因子(通常称为 cost),例如
10表示执行2¹⁰ = 1024次哈希计算 - 这种设计使得每次哈希的计算成本更高,从而增加了破解的难度,同时允许根据硬件性能调整哈希强度
- 加盐存储
- bcrypt 的输出包含了盐值和哈希值,因此在验证时不需要单独存储盐值。其格式为:
$2b$<cost>$<salt><hashed_password>
例如:
$2b$10$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36xrg6P3iGzU3lWRssrZJYu
1
- 抗字典攻击
- 盐值的加入和高成本的哈希计算使得简单的字典攻击效率极低
- 即使使用现代 GPU 进行暴力破解,也需要较长时间才能计算出结果
# bcrypt 的工作流程
- 密码哈希化
用户注册时,调用 bcrypt.hash() 方法:
const bcrypt = require('bcrypt');
const saltRounds = 10; // 工作因子
const plainPassword = 'my_secure_password';
bcrypt.hash(plainPassword, saltRounds, (err, hashedPassword) => {
if (err) throw err;
console.log('Hashed password:', hashedPassword);
});
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- 密码验证
用户登录时,调用 bcrypt.compare() 方法比较明文密码和存储的哈希值:
const inputPassword = 'my_secure_password';
const storedHash =
'$2b$10$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36xrg6P3iGzU3lWRssrZJYu';
bcrypt.compare(inputPassword, storedHash, (err, isMatch) => {
if (err) throw err;
console.log('Passwords match:', isMatch); // true or false
});
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# bcrypt 如何在验证阶段工作
当你调用 bcrypt.compare(plainPassword, hashedPassword),以下步骤会发生:
- 从哈希值中提取信息
- bcrypt 的输出(即存储在数据库中的哈希值)不仅包含了最终的哈希,还包括了以下内容:
- 算法标志(如
$2b$) - 工作因子(如 10,表示
2¹⁰次迭代) - 盐值(随机生成的字符串)
- 最终的加密哈希
- 算法标志(如
- 例如,哈希值:
$2b$10$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36xrg6P3iGzU3lWRssrZJYu
1
分解为:
$2b$:bcrypt 算法版本10:工作因子(cost)EixZaYVK1fsbw1ZfbX3OXe:盐值PaWxn96p36xrg6P3iGzU3lWRssrZJYu:加密后的哈希值
- 重新生成哈希
- bcrypt 从存储的哈希值中提取盐值和工作因子
- 使用提取的盐值和工作因子,将用户输入的明文密码进行相同的哈希过程
- 生成一个新的哈希值
- 对比生成的哈希和存储的哈希
- bcrypt 比较刚刚生成的哈希值和存储的哈希值。如果两者相同,说明密码匹配;否则密码无效
# bcrypt 的优势
- 内置盐值机制
- 每次哈希自动生成唯一盐值,避免手动管理盐值的复杂性
- 提高了密码的随机性,抵御彩虹表攻击
- 可调工作因子
- 工作因子可根据硬件性能调整,增加破解难度
- 即使计算能力提升,增加工作因子后仍可保持安全性
- 抗时间攻击
bcrypt.compare()的实现时间几乎恒定,避免因比较时间不同而泄露信息(时间攻击)
- 内置抗暴力破解
- 高计算成本使暴力破解代价极高,特别是工作因子较高时
- 广泛支持
- bcrypt 是一个成熟的库,支持多种语言和平台,例如 Node.js、Python、PHP 等,便于在不同技术栈中使用
- 结构化输出
- 哈希值包含盐值和工作因子,存储简便,验证过程中无需额外管理
# bcrypt 的局限性
- 性能开销
- 相对于其他轻量级哈希算法(如 SHA-256),bcrypt 的计算开销较高。如果使用过高的工作因子,可能影响用户体验
- 最大支持密码长度
- bcrypt 通常对密码长度有一个上限(如 72 字节),对于非常长的密码,需注意这一点
- 不适合非密码数据
- bcrypt 设计用于保护密码,不适合用于其他需要哈希的场景(如文件校验或签名)
# 与其他哈希算法的比较
| 算法 | 是否适合密码 | 盐值支持 | 计算开销 | 抗暴力破解 | 常见用途 |
|---|---|---|---|---|---|
bcrypt | 是 | 内置支持 | 高 | 强 | 密码存储与验证 |
SHA-256/512 | 否 | 无(需手动) | 低 | 弱 | 数据完整性校验、签名 |
PBKDF2 | 是 | 支持 | 可调 | 强 | 密码存储与加密密钥导出 |
Argon2 | 是 | 支持 | 可调(更高) | 非常强 | 密码存储(现代推荐) |
# link
上次更新: 2025/10/08, 16:24:59