首页/安全/加密与证书速查/口令加盐(Salt)
加密算法基础95 条

口令加盐(Salt)

为每个口令生成唯一随机值并随散列存储,使相同口令得到不同散列,抵御彩虹表与批量比对;盐不是密钥,无需保密但要唯一。

加密与证书速查安全更新于 2026-10-13

加盐在解决什么

加盐是为每个口令生成一段唯一的随机值,与口令一起参与散列,并把盐随散列结果一起存储。它的作用是让相同口令得到不同散列,从而抵御彩虹表以及用户之间的批量比对。盐不是密钥,不需要保密,但必须唯一且足够长;它的价值在于破坏「一次计算、批量命中」的攻击模式。

基本信息

长度建议至少 16 字节随机
存储与散列一起保存,常直接嵌入散列字符串
作用抵御彩虹表、隐藏相同口令
唯一性每个口令一份,改密时必须更换
与 pepper 的区别pepper 是额外秘密,与散列分开保管
常见错误固定盐、全局共享盐、短盐

典型使用场景

  • 口令入库:注册与改密时生成新盐,与散列一起写入
  • 迁移存量数据:为老散列补盐重算,用户下次登录时完成升级
  • 密钥派生:为 KDF 提供每份数据独立的盐,避免相同输入产出相同密钥
  • 审计检查:确认数据库里没有重复盐,也没有短于 16 字节的盐
  • 多应用隔离:不同系统使用不同的额外上下文,避免散列口径互相套用

生成与使用

生成与使用
import os, hashlib, base64
salt = os.urandom(16)                                    # 每个口令独立生成
dk = hashlib.pbkdf2_hmac('sha256', b'password', salt, 600000)
print(base64.b64encode(salt).decode(), base64.b64encode(dk).decode())
# 校验:从存储中取出盐与参数,用同样的流程重算并做常量时间比较
# 改密时必须重新生成盐,不要沿用旧值

概念对照

概念是否需要保密作用
盐不需要,公开存储让相同口令产生不同散列
pepper需要,与散列分开保管增加全局秘密,降低拖库可利用性
迭代次数不需要抬高单次计算成本,需随硬件调整
算法标识不需要记录算法与参数,便于后续升级
固定盐、全局共享盐或短盐(如 4 字节)会让彩虹表重新有效;每次改密都要生成新盐。
盐要与迭代次数一起存:只保留散列与盐、不记录算法与参数,将来调整强度时老数据就无法校验。
盐只提高攻击成本而不消灭可能:攻击者仍可针对单个目标穷举,所以必须叠加慢散列与足够强度的口令策略。

易错点

  • 盐要和散列一起存储且格式明确,混用 base64 与 hex 编码会导致校验失败
  • 给盐加 pepper 是可选项,但 pepper 丢失意味着全部口令无法校验,需有备份与轮换流程
  • 固定盐或全局共享盐会让彩虹表重新生效
  • 盐长度过短(如 4 字节)在大量用户下会出现碰撞,削弱效果
  • 改密时沿用旧盐,会把新旧两次散列关联起来

数据来源与参考

  • OWASP Password Storage Cheat Sheet
  • RFC 8018 §4.1(盐的用途)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌