密码加密存储方案:bcrypt、scrypt、Argon2 对比

详细介绍密码加密存储的最佳实践,对比 bcrypt、scrypt、Argon2 等算法的特点和适用场景。

加密与哈希 2026-06-01 8 分钟

密码加密存储方案: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

作用:

  1. 防止彩虹表攻击
  2. 相同密码产生不同哈希值
  3. 每个用户使用独立的随机盐

Spring Security 密码配置

@Configuration
public class SecurityConfig {
    @Bean
    public PasswordEncoder passwordEncoder() {
        // 推荐使用 bcrypt
        return new BCryptPasswordEncoder(12); // 成本因子 12
    }
}

最佳实践

  1. 使用 bcrypt 或 Argon2:不要自己实现加密算法
  2. 合理的成本因子:bcrypt 成本因子 10-12
  3. 每个用户独立盐:自动生成随机盐
  4. 定期升级:随着硬件升级,增加成本因子
  5. 限制登录尝试:防止暴力破解

总结

密码存储是系统安全的基石。使用 bcrypt 或 Argon2,配合随机盐和合理的成本因子,可以有效保护用户密码。

📚 相关文章