跳转至

密码安全存储相关问题

一、绝对不能做的事

  1. 明文存储:数据库泄露后所有密码暴露。
  2. MD5 / SHA1 直接存:彩虹表可秒破。
  3. 自己发明加密算法

二、正确做法:加盐 + 慢哈希

1. 为什么不能用普通哈希

MD5、SHA256 计算太快,攻击者拿到数据库后可以用 GPU 每秒试上亿次。

2. 加盐(Salt)

每个用户一个随机 salt,和密码一起哈希。即使两个用户密码相同,存的哈希也不同。

hash = Hash(password + salt)

salt 可以和哈希一起明文存(salt 不是密钥)。

3. 慢哈希

故意设计得慢,让攻击者暴力破解成本高。

算法 特点
bcrypt 自适应,默认推荐
PBKDF2 NIST 推荐
Argon2 2015 密码哈希竞赛冠军
scrypt 内存困难函数

三、代码示例(bcrypt)

Spring Security:

// 注册
String hash = new BCryptPasswordEncoder().encode("mypassword123");
// 存数据库

// 登录
boolean match = new BCryptPasswordEncoder()
    .matches("mypassword123", hash);

BCrypt 自动把 salt 编码进哈希字符串,不需要单独存 salt。

四、为什么 bcrypt 慢

它内部做几千次迭代(cost factor):

BCrypt.hashpw(password, BCrypt.gensalt(12))

12 表示 2^12 = 4096 次迭代。硬件升级后可调大 cost。

五、其他要点

  • 传输用 HTTPS:不要让密码在网络上明文。
  • 不要记录密码:日志里不能打密码。
  • 密码强度策略:长度、复杂度、过期。
  • 多因素认证(MFA):密码之外加短信 / 验证器。
  • 登录失败锁定:防爆破。

六、为什么不能用可逆加密存密码

即使加密,密钥泄露就能解密。哈希是单向的,连运维都看不到用户密码。

面试加分

  • 答出"加盐 + 慢哈希(bcrypt/Argon2)"就是满分答案。
  • 为什么 MD5 不行:快 + 彩虹表。