PHP 密码盐真的有必要吗?

Is PHP password salt really necessary?

这个问题我已经问过自己十几次了。

密码盐真的有必要吗?

我找不到关于这个主题的任何好的文献。

从安全角度来看,密码盐有帮助吗? 如果数据库被攻破了,如果密码还在,盐不就丢了吗?

另外,从刷力的角度来看,如果我封IP了,真的有必要存盐吗?

是的,您应该始终使用盐。幸运的是 PHP 非常聪明。来自 this article:

If you use the default options for the password_hash() function PHP will generate a random salt for each password as it is hashed. The random salt is an additional layer of security which makes it exceptionally hard to crack any passwords. Even if two or more users use the same password each of their hashes will be different.

这使您不必生成盐,而将繁重的工作留给 PHP。验证部分 password_verify() 使用散列中的随机盐来测试给定的密码。

来自 password_verify() 的文档:

Note that password_hash() returns the algorithm, cost and salt as part of the returned hash. Therefore, all information that's needed to verify the hash is included in it. This allows the verify function to verify the hash without needing separate storage for the salt or algorithm information.

它确实有助于对抗 'rainbow tables',它们是已知密码的预编译哈希值。当你对密码加盐时,它们就没用了,因为散列值会不同。

确实需要加盐,因为未加盐的哈希太容易破解(使用rainbow tables)。

首先,未加盐的哈希会导致更多的冲突。如果两个密码使用 baseball 作为密码,破解一个就足以破解两个。如果两者都加盐,那么一个变成baseball#sd7#$j,一个变成baseballL4&$h1,那是行不通的。

其次,像 baseball 甚至 *4kB$l!h_' 这样的密码如果没有加盐的话,很容易使用 rainbow tables 来逆转。这是因为很容易创建彩虹 table 覆盖所有密码,直到一定长度。但是,如果适当加盐,*4kB$l!h_' 可能会变成 *4kB$l!h_'H4Sj)@80-+2nm:W[oa}u#*4$lNamA{ 或其他长得离谱的东西。为此生成彩虹table要困难得多。

使用 PHP,让您的生活更轻松,只需使用 password_hash()。无论您做什么,都不要推出自己的安全算法, 尤其是在密码存储方面。你被烧死。

有关更多信息,请阅读 Why are salted hashes more secure? You may also want to spend some time with OWASP's Password Storage Cheat Sheet and it's PHP Security Cheat Sheet

我想指出使用盐的真正目的。正如另一个答案中所解释的,不同的盐会导致相同密码的不同哈希值,但这是 不是 的主要目的。

通过对每个密码使用不同的盐,您可以防止构建一个彩虹table一次获取所有密码

正如您所写,盐不是秘密。要获得单个密码,攻击者仍然可以使用这种已知的盐来构建彩虹 table。问题是,他(她)必须为第二个密码构建第二个彩虹 table,因为它使用了不同的盐。换句话说,第一个彩虹table不能被重复用来寻找其他密码。

构建彩虹 table 只得到一个密码没有意义,brute-force 更容易,直到找到匹配项,计算彩虹的其余部分 table 是无用的,因为你不能重复使用它。这就是为什么我们说,独特的盐可以防止彩虹 table 攻击,因为 brute-forcing 比使用彩虹 tables 更快。