Ryan

密码该怎么存:OWASP 密码存储备忘单摘抄

Argon2id 该用什么参数、bcrypt 为什么有 72 字节上限、为什么不该强制换密码——把 OWASP 官方备忘单里最能直接落地的几条抄下来。

评论
密码该怎么存:OWASP 密码存储备忘单摘抄

「密码该怎么存」这件事,网上的说法多到互相矛盾:有人说 bcrypt 够了,有人说必须上 Argon2,有人说要三个月换一次,有人说换了反而更糟。与其在论坛里吵,不如直接抄标准答案——OWASP 的《Password Storage Cheat Sheet》是这一领域引用最广的权威清单,下面把最硬、最能直接落地的几条摘出来。

一、算法选择:Argon2id 是第一梯队

OWASP 给出的优先级里,Argon2id 排在第一位,官方推荐的最低配置是:

m = 19456  (19 MiB 内存)
t = 2      (迭代 2 次)
p = 1      (并行度 1)

三个参数各管一件事,理解它们就知道了为什么它比哈希「贵」:

  • m(内存)是抗 GPU 的核心——显卡最缺的就是显存带宽;
  • t(迭代)拉长单次计算时间,抬高暴力破解成本;
  • p(并行度)决定能同时吃几个核,服务端一般保持 1 即可。

排在第二梯队的是 scrypt(N=2^17, r=8, p=1),如果环境不支持 Argon2 再考虑它。

二、bcrypt 的两个坑

bcrypt 至今仍是可接受的选择,但用它必须知道两件事:

  • work factor 不能低于 10——这是官方给的底线,低于此值在现代硬件面前形同虚设;
  • 输入上限 72 字节,超出部分被静默截断。这条最阴险:密码 + 后面随便加什么 都能通过验证,等于把有效密码长度砍到了 72 字节。

绕过截断的标准做法是先做一次定长摘要再交给 bcrypt:

base64( SHA-256( password ) )  →  bcrypt( ... )

这样无论原密码多长,送进去的都是固定不超过 72 字节的串。

三、参数必须跟着哈希一起存

算法、work factor、盐、成本参数——全部要随哈希一起持久化。好消息是主流库(Argon2 的 PHC 格式、bcrypt 的 $2a$11$...)天生就是自描述字符串,参数直接写在哈希里,不需要你另建字段。这也是为什么「以后想调高成本」是可行的。

四、登录成功的那一刻,顺手升级

这是整份文档里最容易被忽略、收益却最高的一条:

当用户正确登录、你手上正好有明文密码时,检查一下存着的哈希是不是还在用旧参数;如果是,立即用新参数重新哈希并存回去。

它的妙处在于:不需要强制任何人改密码,老用户的哈希会随着他们日常登录,无声无息地全部升级到新标准。

五、不要做的事

  • 不要强制周期性更换密码。官方明确不支持这种做法——它带来的是可预测的弱化(Spring2026! → Summer2026!),而不是安全;
  • 不要用「安全问题」做二次验证。母亲的娘家姓这类答案,往往比密码更容易被查到;
  • 不要自己发明加密方案,也不要拿 MD5/SHA-1/SHA-256 裸哈希当密码存储。

另外两条值得加进注册流程:对照已泄露密码库(如 Have I Been Pwned)拒绝 Weak 密码,以及限制密码长度上限(避免超长输入造成 DoS)。

六、出处

  • OWASP Cheat Sheet Series — Password Storage Cheat Sheet
    https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html

七、在自家服务器上的印证

这份备忘单不是纸上谈兵——本站这台服务器跑的几套服务,恰好各用了其中一种:

  • Vaultwarden:管理令牌用 Argon2id 的 PHC 字符串($argon2id$v=19$m=65536,p=4,t=3$...),一眼就能读出内存 64 MiB、4 路并行、3 次迭代——正是「参数自描述」的活例子;
  • WireGuard 面板:密码哈希由容器内的 argon2 库生成;
  • 日志面板:用的是 bcrypt,哈希前缀 $2a$11$ 里的 11 就是 work factor,刚好卡在官方要求的 ≥10 线上。

凡是自己部署过一遍的人都会有同感:这些参数不是可以随便填的,它们就是你面对离线爆破时唯一的防守纵深。

评论

推荐阅读

订阅邮件

订阅更新,及时收到最新文章。

作者