跳转到主要内容

盐值

本文约需 2 分钟阅读

盐 (Salt) 是指对密码进行哈希处理时附加的随机数据。即使是相同的密码,只要盐不同就会生成不同的哈希值,因此可以使彩虹表攻击和预计算攻击失效。盐为每个用户唯一生成,并与哈希值一起保存。

盐的工作原理与数值示例

在对密码进行哈希处理时,用密码学安全的随机数生成器生成盐,将其与密码结合后再输入哈希函数。例如,给密码「mypassword」附加 16 字节 (128 位) 的盐,即使是相同的密码也会为每个用户生成完全不同的哈希值。盐的推荐长度为 16 字节以上,bcrypt 中标准为 128 位,Argon2 中标准为 128 位以上。截至 2025 年的 OWASP 指南推荐 Argon2id 与 16 字节以上的盐相结合。盐无需保密,可与哈希值一起保存在数据库中。重要的是为每个用户使用不同的盐。

用 SHA-256 对同一密码「mypassword」进行哈希处理时
用户盐 (16 字节、前 8 位)哈希值的前 16 位
用户 A (无盐)无89e01536ac207279...
用户 B (无盐)无89e01536ac207279...
用户 A (有盐)8f2b7c1d...58ef28c75d1f8e9e...
用户 B (有盐)1a4c9e2b...f8250873b0d4600e...

无盐的两行得出相同的值,这正是彩虹表能够奏效的原因。下面两行为每个用户加了不同的盐,即使密码相同,得出的值也毫无共同点。

如何迁移未加盐的既有系统

要把既有系统从未加盐的保存方式迁移过来时,无法直接把已保存的哈希值重新生成。因为哈希无法逆推,服务方并不持有用户的明文密码,也就没有可用于计算新方式哈希的材料。因此,迁移的推进方式是等到用户下一次登录并输入正确密码时,用该值生成新方式的哈希,替换掉旧的记录。它无法通过一次操作完成,而是随着登录频率逐步替换、需要时间的工作。长期未登录用户的记录会继续保持旧方式,因此需要作出诸如设定期限、要求重设密码之类的判断。迁移期间数据库内新旧方式并存,所以设计上还需要能够判别某一条记录是用哪种方式保存的。如果仍以未加盐的方式继续运行,这次迁移所需的时间本身,就成为左右泄露时损害规模的一个因素。

为什么需要盐

如果没有盐,使用相同密码的用户全都会得到相同的哈希值。攻击者可以使用彩虹表一次性破解大量密码。用具体数值来看,在没有盐的情况下,攻击者只需一张彩虹表 (数百 GB 左右) 即可攻击全部用户的密码。但若使用 16 字节的盐,理论上需要 2 的 128 次方种表,预计算攻击在实际上将变得不可能。

实务中的陷阱

常见的错误是对所有用户使用相同的盐,这会大幅降低使彩虹表失效的效果。同样,如果盐的长度过短 (例如 4 字节以下),攻击者也能制作出涵盖所有盐模式的表。另一个陷阱是试图将盐作为「秘密」保存在其他地方。盐的目的是确保唯一性而非保密,因此与哈希值保存在同一数据库中没有问题。随机生成的密码本身就难以猜测,但与服务端的盐实现相结合,可以实现更为坚固的保护。

相关术语

这篇文章对您有帮助吗?