什么是加盐?
加盐(Salting)是指在密码哈希过程中,为每个用户密码附加一段随机数据(盐值),然后再进行哈希计算。盐值通常是随机生成的,并与哈希结果一起存储。即使两个用户使用相同的密码,加盐后产生的哈希值也会完全不同。
为什么要加盐?
不加盐的密码哈希存在以下风险:
- 彩虹表攻击:攻击者可以预先计算常用密码的哈希值,形成彩虹表,快速反向查询原始密码。
- 相同密码可识别:如果多个用户密码相同,他们的哈希值也相同,攻击者可以据此推测密码相同。
- 并行破解:攻击者可以对所有哈希值同时尝试一个密码,提高破解效率。
加盐可以有效防御上述攻击:彩虹表无法预计算带随机盐的哈希;即使密码相同,哈希也不同;攻击者只能逐个破解每个盐值下的密码。
加盐的最佳实践
- 使用足够长的随机盐:建议至少16字节(128位),使用密码学安全的随机数生成器。
- 每个用户使用独立盐:即使同一个用户更改密码,也应生成新盐。
- 盐与哈希一起存储:通常将盐拼接在哈希值前,或单独存入字段,以便验证时使用。
- 结合慢哈希算法:仅加盐还不够,应使用计算成本高的算法(如bcrypt、PBKDF2、Argon2)来抵抗暴力破解。
加盐的实现方式
基本公式:hash = H(salt || password) 或 hash = H(password || salt),但更安全的是使用标准密钥派生函数,如PBKDF2:
salt = random_bytes(16) hash = pbkdf2(password, salt, iterations=100000, key_length=32, algorithm='sha256') 存储格式:hash:salt:iterations
示例(PHP)
// 生成哈希(使用内置password_hash自动加盐)
$hash = password_hash($password, PASSWORD_DEFAULT);
// 验证
if (password_verify($password, $hash)) {
// 密码正确
}
现代语言库(如PHP的password_hash、Python的passlib)已自动处理加盐和慢哈希,开发者应优先使用这些标准API。
常见误区
- 盐太短或固定:固定盐等同于没有加盐。
- 盐未与哈希一起存储:验证时需要相同的盐。
- 只加盐不慢哈希:GPU加速的暴力破解仍可能快速破解短密码。
- 盐与密码简单拼接而不使用密钥派生函数:可能导致长度扩展攻击等。
总结
加盐是密码存储的基本安全措施,必须与慢哈希算法结合使用。开发者应使用经过充分测试的密码哈希库,避免自行实现,从而确保用户密码的安全性。