← [ BACK_TO_NOTES ]

Password Storage & Verification

密码验证系统应把用户口令经过独立随机 salt 和自适应 password-hashing scheme 存成带算法/参数版本的 verifier,并结合可选 pepper、登录速率限制和 rehash-on-login 抵抗数据库泄漏后的离线猜测;它与可逆加密和普通 SHA-256 不同。

#synthesis #evergreen #auth #crypto

[!info] related notes

Password Storage & Verification

一句话模型

服务端不应该保存“可恢复原密码”的值。

典型模型:

password + unique salt + password-hashing parameters → slow/adaptive password hash → stored verifier

登录时:

candidate password → same scheme using stored parameters → constant-time/algorithm verify → match / mismatch

Threat Model

Password storage 主要防的是:

attacker 拿到了 user database 之后进行 offline password guessing。

此时 attacker 已经拥有:

  • stored hash;
  • salt;
  • algorithm name;
  • work factor;
  • 可能的用户 metadata。

系统无法阻止 attacker 无限离线尝试,只能让每一次 guess 尽可能昂贵。

因此 password hashing 需要:

  • unique salt;
  • tunable cost;
  • ideally memory hardness;
  • algorithm/version metadata;
  • periodic parameter upgrade。

为什么不能直接 SHA-256

普通 SHA-256 设计目标是高吞吐。

对于低熵人类口令:

password → SHA-256 → hash

attacker 可以用 GPU/ASIC 每秒尝试巨量候选。

所以:

cryptographic hash 安全 ≠ password storage 安全。

详见 密码学哈希函数。

Password Hashing Scheme

现代优先:

兼容/合规场景:

已有 legacy 系统常见:

选择不应只看算法名字,还要看当前参数和平台支持。

Salt

每个 password verifier 使用独立、随机 salt。

目标:

  • 相同 password 不产生相同 stored verifier;
  • 阻止跨账号一次计算复用;
  • 破坏通用 rainbow table。

Salt:

  • 可以和 hash 一起存;
  • 不要求保密。

详见 Salt vs Pepper。

Pepper

Pepper 是额外的 server-side secret。

它不和 password hash 放在同一数据库中,理想上存于:

  • HSM;
  • KMS;
  • TEE;
  • 独立 secret store。

它提供 defense in depth:

database dump leaked but pepper still secret → offline cracking becomes much harder

Pepper 不是 salt 的替代品。

存储格式

不要只存一列裸 digest。

至少需要能够恢复:

  • scheme/version;
  • parameters;
  • salt;
  • output/hash。

许多算法采用自描述字符串,例如 PHC string。

这样才能支持:

登录成功时检测旧参数 → rehash → 升级 verifier。

Rehash-on-Login

推荐迁移策略:

  1. 用户使用旧 verifier 登录;
  2. 先按旧 scheme 正常 verify;
  3. 登录成功;
  4. 判断参数是否低于当前 policy;
  5. 用当前 scheme/参数重新 hash;
  6. 原子更新 verifier。

这样不需要知道用户明文密码,也能渐进升级整个数据库。

在线攻击与离线攻击不同

Password hashing 主要提高 offline guessing 成本。

在线 login attack 还必须依赖:

  • rate limiting;
  • account throttling;
  • suspicious-login detection;
  • MFA;
  • breached-password screening。

不要通过把 Argon2 参数调到极高来替代 online rate limiting。

DoS 边界

Password hashing 故意昂贵,也会消耗真实服务器资源。

如果:

  • memory cost 太高;
  • parallelism 太高;
  • 无登录 rate limit;

攻击者可能利用登录 endpoint 制造资源耗尽。

因此参数应按:

security target

  • hardware benchmark
  • expected concurrency
  • latency budget

共同调优。

Password Verification 不等于 Password-Derived Encryption

服务端登录:

password → verifier → yes/no

密码保险库/本地加密:

password → KDF → encryption key → decrypt vault

两者都可能用 Argon2/PBKDF2,但产物和系统目标不同。

不要把“password hash”与“由 password 派生出的长期 encryption key”混成同一对象。

当前标准边界

NIST SP 800-63B-4 要求密码 verifier:

  • 使用适合 password hashing 的 salted scheme;
  • cost factor 尽可能高但不破坏 verifier 性能;
  • 随计算能力增长提高 cost;
  • 存储 scheme / cost metadata 以支持迁移;
  • 可额外使用单独保存的 keyed secret 作为额外防线。

OWASP 当前优先推荐 Argon2id;FIPS-140 合规需要时可使用 PBKDF2-HMAC-SHA256。

参数数字应被视为当前基线,不是永久常数。

常见错误

hash(password + salt)

自己拼普通快速 hash。

→ 不等于标准 password hashing scheme。

全站共用一个 salt

→ 失去 per-account salt 的关键价值。

Salt 当 secret

→ 没必要,反而使设计复杂。

Pepper 和数据库一起存

→ 数据库泄漏时 pepper 同时泄漏,防御价值大幅下降。

永远固定 cost

→ hardware 变快后离线攻击成本持续下降。

登录失败就自动升级 hash

→ 没有正确 password 时不能安全 rehash。

学习检查

  1. Password storage 的核心 threat model 为什么是 database breach 后的 offline guessing?
  2. 为什么 SHA-256 本身安全却不适合直接存 password?
  3. Salt 为什么需要 unique/random,却不需要保密?
  4. Pepper 为什么必须和 hash database 分离?
  5. 为什么 verifier 应存 scheme 与参数 metadata?
  6. rehash-on-login 怎样在不知道长期明文密码的情况下升级算法?
  7. password hashing 与 online rate limiting 分别解决什么攻击面?
  8. password verifier 与 password-derived encryption key 有什么不同?
创建于 2026/9/30 更新于 2026/9/30
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本