Skip to content

密码为什么要加密存储?BCrypt 的原理是什么?相比 MD5+盐有什么优势? ​

  • 标签:Spring Security、认证授权、后端

🏛 业务架构师 ​

密码必须加密存储(准确说是单向哈希+盐)的理由:数据库随时可能被拖(SQL 注入、备份泄露、内部人员)——明文密码一泄,攻击者拿它撞库(用户在别处用同一密码),损失放大到用户的其他账户;监管上(个保法、等保)密码明文存储属于重大违规,可直接处罚。

BCrypt 原理:

  1. 基于 Blowfish 算法改造的可调成本哈希:自带随机盐(每次哈希结果都不同,盐直接编在输出里 "$2a$10$salt+hash",无需单独存盐);
  2. 成本因子(work factor,如 10 = 2^10 轮迭代):可随硬件进步调高——摩尔定律下"算力变便宜"的对抗手段,哈希一次约 100ms,暴力破解一个 8 位密码的成本指数级上升;
  3. 输出 60 字符定长。

相比 MD5+盐的优势:

维度MD5+盐BCrypt
速度微秒级(对攻击者是好事——GPU 每秒可算千亿次)慢 5 个数量级(专为"慢"设计)
盐管理要自己生成、存储、防重复盐内置自动盐
算法抗性MD5 已被碰撞攻破、GPU/彩虹表加速成熟专为密码设计,抗 GPU 并行(内存依赖)
可调强度无成本因子随硬件升级

业务落地:Spring Security 默认就是 BCrypt(PasswordEncoderFactories.createDelegatingPasswordEncoder())——带版本前缀的委托设计支持未来升级算法(旧密码兼容验证、逐步重哈希)。安全底线三件套:BCrypt 存储、HTTPS 传输、登录失败限流——这套默认配置别去"优化"它。

🏗 系统架构师 ​

密码必须加密存储 = 数据库泄露时的最后防线:明文/可逆加密一旦拖库,全部账户即刻沦陷(且撞库攻击蔓延到用户其他账户);密码学原则——密码不需要"可恢复",只需要"可验证",所以用单向慢哈希。

BCrypt 原理(三层设计):

  • 自适应慢哈希:基于 Blowfish 改造,成本因子(cost/rounds)控制迭代轮数——每 +1 轮耗时翻倍(默认 10 ≈ 100ms 量级);硬件进步时调高 cost 保持"慢"——对抗 GPU/ASIC 暴力枚举(单次 100ms,攻击者每秒只能试几十个,而不是 SHA256 的每秒百亿次);
  • 内建盐(salt):每次哈希随机生成 16 字节盐,防彩虹表与相同密码同密文(盐嵌在输出里,无需单独存储列);
  • 输出自包含:$2a$10$[salt][hash]——算法版本、cost、盐、密文一个字符串,验证时从密文自身解析参数(升级 cost 只改新密码,老密文按自己的 cost 验)。

相比 MD5+盐 的优势:

  • MD5 太快:通用哈希为速度设计——GPU 每秒数十亿次,任何盐都挡不住暴力枚举(盐只防彩虹表,不防穷举);
  • 盐的管理成本:MD5+盐要自己处理盐生成、存储、拼接——实现错误率高(盐复用、拼接顺序错);BCrypt 一体化无心智负担;
  • 无升级机制:MD5 方案要提高强度要全量重哈希;BCrypt 的 cost 透明内嵌(DelegatingPasswordEncoder 还支持 {bcrypt} 前缀多算法共存与迁移)。

架构实践:Spring Security 默认 BCryptPasswordEncoder(cost 10 起步,按硬件调到目标 100ms);同类替代 Argon2(内存困难,抗 ASIC 更强,新系统可选);已有 MD5 存量:登录时透明升级(MD5 验证通过 → 重哈希成 BCrypt 落库),平滑迁移不停机。

💻 全栈开发专家 ​

为什么必须加密存储:数据库泄露(拖库)、内部人员、备份文件流转——明文密码一旦暴露,撞库连带伤害是指数级的。密码存储的铁律是只存「可验证不可还原」的形式。

BCrypt 原理:

  1. 基于 Blowfish 改造的可调代价函数:内置盐(随机 16 字节)+ 成本因子 cost(默认 10,2^cost 轮);
  2. 输出自带元数据:$2a$10$[22位盐][31位哈希]——盐嵌在结果里,无需单独存储;
  3. 慢得恰到好处:cost=10 约 100ms/次——正常登录无感,暴力破解则每猜一次都要 100ms,GPU 也要硬扛;cost 可随硬件升级调到 12/14(未来防暴力能力可持续增强);
  4. 盐在 BCrypt 内部参与多轮加密(不是简单拼接),对抗彩虹表和 GPU 并行。

相比 MD5+盐的优势:

MD5+盐BCrypt
速度微秒级(GPU 万亿/秒)故意慢(百毫秒级)
盐要自己生成/存储/防逻辑错内置、自包含
抗暴力cost 固定,硬件升级=防线失守cost 可调,可持续加固
算法MD5 已被密码学界判死刑(碰撞)专为密码设计 + 20 年实战

Spring 工程实践:

java
@Bean
PasswordEncoder passwordEncoder() { 
    return new BCryptPasswordEncoder(12);        // 新项目建议 12
}
// 存:encoder.encode(rawPwd)    验:encoder.matches(rawPwd, hashed)

升级坑:已有 MD5 存量密码——「入职加密」策略:登录成功时用 BCrypt 重编码更新(DelegatingPasswordEncoder 的 {bcrypt} 前缀方案支持多算法共存渐进迁移)。同类推荐:Argon2(抗 GPU/ASIC 更强,内存困难函数)、scrypt;它们仨都比 MD5/SHA 系强几个量级。