在密码哈希里必然会出现的「salt(盐)」。就像做菜时的盐一样,给哈希加上一小撮,安全性就会大不相同。本文讲解其机制与要点(不会写出攻击步骤)。
为什么「调味」能起作用
没有 salt 时,密码相同的人保存的哈希也相同。这给了攻击者两条近路——预先计算好的对照表(彩虹表)能直接命中,以及「一个人的破解结果,可以套用到所有密码相同的人身上」。
加上 salt 后,即便同样是 "password123",每个用户的保存值也会完全不同。
出于同样的道理,salt 必须每个用户(最好是每个密码)都重新创建。如果所有人共用同一个 salt,相同密码的人之间保存值又会一致,好不容易得来的效果就被削弱了。生成时要使用难以猜测的密码学随机数,创建好的 salt 要和哈希值一起保存(无需保密)。
另外,salt 守护的范围仅限于「预先计算好的表」和「针对重复使用密码的批量破解」。针对单个密码进行穷举的攻击本身,让它变慢并不是 salt 的工作,而是由 bcrypt/Argon2 这类故意做得很慢的哈希来承担。两者的守备范围不同,所以必须搭配使用。
常见误解与正解
误解
- salt 必须保密
- 所有用户用共同的 salt 就行
- 只要加上 salt,弱密码也安全
正解
- salt 以公开为前提即可(和哈希一起保存)
- 每个用户(最好是每个密码)用不同的随机数
- salt 是针对「预先计算与重复使用密码破解」的对策。穷举对策由慢速哈希承担
本站的观点:salt 和 pepper 是两种东西
容易与 salt 混淆的是 pepper(胡椒)。pepper 是给全体添加的秘密值,放在和数据库不同的地方(应用配置或密钥管理)。salt(公开·每个用户)和 pepper(秘密·全体共用)角色不同,任何一方都无法替代另一方。话虽如此,实务上首先要做的,是用 bcrypt/Argon2 正确地实现salt+慢速哈希。
接下来阅读
- 术语:密码哈希是什么(与 salt 成对理解)
- 对策:密码的安全保存方法(哈希+salt 实践)
- 入门:密码的正确保管
FAQ
Qsalt 必须保密吗?
不必。salt 不是『秘密的密钥』,可以和哈希值一起保存。它的目的不是保密,而是让相同密码的人保存值也各不相同,从而使预先计算(彩虹表)和针对重复使用密码的批量破解失效。需要保密的是另一种东西『pepper』(后述)。
Q所有用户能不能共用同一个 salt?
不行。salt 必须是每个用户(最好是每个密码)各不相同的随机值,这一点至关重要。如果用共同的 salt,相同密码的人之间保存值就会一致,攻击者只需一次穷举就能成批攻破多个账户。每次新生成时都要用密码学随机数来创建。
Q需要自己实现 salt 吗?
通常不需要。bcrypt、Argon2、scrypt 这类专用哈希会自动完成 salt 的生成与保存(大多直接同梱在哈希字符串之中)。比起自己添加 salt,把它交给这些标准实现更安全、更可靠。