密码加密存储方案:bcrypt、scrypt、Argon2 对比
密码存储是系统安全的核心。本文介绍密码加密存储的最佳实践。
❌ 错误的密码存储方式
1. 明文存储
// 绝对不要这样做
String password = "123456";
user.setPassword(password); // 数据库中直接存储明文
2. 简单哈希
// 不安全:彩虹表可以破解
String hash = MD5(password);
3. 哈希 + 固定盐
// 不安全:盐应该是随机的
String hash = SHA256(password + "fixed_salt");
✅ 正确的密码存储方式
bcrypt(推荐)
bcrypt 是目前最常用的密码哈希算法。
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
// 加密
String hash = encoder.encode("mypassword");
// $2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy
// 验证
boolean matches = encoder.matches("mypassword", hash);
特点:
- 自适应成本因子(可以随硬件升级增加计算量)
- 内置随机盐
- 输出包含算法版本、成本因子、盐、哈希值
scrypt
scrypt 是内存密集型算法,抗 GPU/ASIC 攻击。
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;
SCryptPasswordEncoder encoder = new SCryptPasswordEncoder(
16384, // CPU 成本
8, // 内存成本
1, // 并行度
32, // 密钥长度
64 // 盐长度
);
String hash = encoder.encode("mypassword");
boolean matches = encoder.matches("mypassword", hash);
特点:
- 内存密集型,抗硬件加速攻击
- 可调参数多
- 比 bcrypt 更安全
Argon2(最新标准)
Argon2 是 2015 年密码哈希竞赛的获胜者。
import de.mkammerer.argon2.Argon2Factory;
Argon2 argon2 = Argon2Factory.create();
// 加密
String hash = argon2.hash(10, 65536, 1, "mypassword".toCharArray());
// 验证
boolean matches = argon2.verify(hash, "mypassword".toCharArray());
特点:
- 2015 年密码哈希竞赛获胜者
- 可同时抵抗 GPU 和 ASIC 攻击
- 推荐新项目使用
算法对比
| 特性 | bcrypt | scrypt | Argon2 |
|---|---|---|---|
| 抗 GPU | 中 | 强 | 最强 |
| 抗 ASIC | 中 | 强 | 最强 |
| 内存消耗 | 低 | 高 | 可调 |
| 参数灵活性 | 低 | 中 | 高 |
| 成熟度 | 高 | 中 | 中 |
| 推荐度 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
盐(Salt)的作用
盐是随机数据,与密码混合后一起哈希。
密码: "123456"
盐: "random_salt_abc"
哈希: SHA256("123456" + "random_salt_abc") → 结果1
另一个用户:
密码: "123456"
盐: "random_salt_xyz"
哈希: SHA256("123456" + "random_salt_xyz") → 结果2
作用:
- 防止彩虹表攻击
- 相同密码产生不同哈希值
- 每个用户使用独立的随机盐
Spring Security 密码配置
@Configuration
public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
// 推荐使用 bcrypt
return new BCryptPasswordEncoder(12); // 成本因子 12
}
}
最佳实践
- 使用 bcrypt 或 Argon2:不要自己实现加密算法
- 合理的成本因子:bcrypt 成本因子 10-12
- 每个用户独立盐:自动生成随机盐
- 定期升级:随着硬件升级,增加成本因子
- 限制登录尝试:防止暴力破解
总结
密码存储是系统安全的基石。使用 bcrypt 或 Argon2,配合随机盐和合理的成本因子,可以有效保护用户密码。