跳转到主要内容

密码哈希

本文约需 2 分钟阅读

密码哈希化是指将用户的密码转换为不可逆的固定长度值后再存入数据库的技术。即使数据库万一发生泄露,也无法从哈希值还原出原始密码,因此能够将损失降到最低。以明文保存密码,是现代安全标准所不能容许的严重设计失误。

明文保存的危险性

以明文 (原样字符串) 保存密码的危险性,已被过去的大规模事件所证明。 2009 年的 RockYou 事件中,约 3,200 万条密码以明文形式泄露。攻击者在获取数据库的瞬间就掌握了全部用户的密码,而重复使用密码的用户在其他服务上也遭受了损害。该事件是向世界展示明文保存密码会招致何等毁灭性后果的标志性案例。关于信息泄露时的应对,我们在信息泄露应对指南中有详细说明。

密码哈希化的整体流程

输入密码
加入盐值
密钥拉伸 (反复数千至数万次)
将哈希值存入数据库

通用哈希不适合用于密码的原因

SHA-256 和 SHA-512 是密码学上安全的哈希函数,但并不适合用于密码的哈希化。原因在于它们「太快了」。 SHA-256 每秒可进行数十亿次哈希计算,使用 GPU 还能进一步加速。对攻击者而言,这意味着可以在短时间内尝试数量庞大的密码候选。专用于密码的哈希函数通过有意减慢计算来应对这一问题。

盐值与胡椒值的作用

盐值

为每个用户在密码上附加一个各不相同的随机值后再进行哈希化。即使是相同的密码,只要盐值不同哈希值就会改变,因此能够使彩虹表攻击失效。盐值会与哈希值一起保存在数据库中。

胡椒值

它是全体用户共用的秘密值,保管在与数据库不同的位置 (如环境变量或 HSM)。即使数据库泄露,没有胡椒值也无法重新计算哈希,因此可作为额外的防御层发挥作用。不过由于密钥管理的复杂度会增加,是否引入需慎重判断。

密钥拉伸的概念

密钥拉伸是一种通过有意将哈希计算重复数千次、数万次,来延长单次哈希计算所需时间的手法。对正规用户的登录而言只需计算一次,因此数百毫秒的延迟在可接受范围内;但当攻击者尝试数亿个密码候选时,每次的延迟会累积起来,使攻击变得不切实际。Argon2bcrypt 内置了密钥拉伸机制。

当代推荐的算法

截至 2025 年,OWASP 的推荐顺序如下。

1. Argon2id
2. bcrypt
3. scrypt
4. PBKDF2

新建系统请选择 Argon2id。现有系统若使用 bcrypt 且成本因子在 12 以上,则无需急于迁移。若单独使用 MD5 、 SHA-1 、 SHA-256 进行密码哈希,应尽快迁移到上述任意一种。为将凭据泄露的风险降到最低,选择合适的算法不可或缺。加密的基础知识可在加密基础这篇文章中学习。密码技术与密码保护书籍 (Amazon)也可作为实现时的参考。

常见的误解

人们常有「只要加密就安全」的误解。加密是只要有密钥就能解密的双向变换,一旦密钥泄露,全部密码会一次性暴露。保存密码的正确做法是哈希化 (单向变换)。此外,「只要把盐值保密就无需胡椒值」的想法也是错误的。由于盐值与哈希值一起保存,数据库泄露时会同时暴露。胡椒值正是因为保管在与数据库不同的位置,才能成为额外的防御层。关于安全密码运营的整体情况,请参阅安全密码管理指南

相关术语

这篇文章对您有帮助吗?

XHatena