6

我正在阅读 PHP 中的密码安全性,偶然发现了一个有趣的声明:

将密码作为盐的哈希值进行哈希处理,返回相同的哈希值

没有多想,我去了php.net,发现那是同样的事情。

让我们看一个例子:

crypt("test", "test"); -> teH0wLIpW0gyQ
crypt("test", "teH0wLIpW0gyQ"); -> teH0wLIpW0gyQ

我完全可以理解 PHP 中的 crypt 会生成给定字符串的单向哈希。

  1. 我不明白的是我们如何使用两种完全不同的盐获得相同的哈希输出?
  2. 这是否意味着可能有其他盐可以给我相同的哈希值?

跟进

谢谢大家的指点。我现在可以看到默认行为是只使用 salt 的前两个字符,这完全回答了我的所有问题。感觉很傻,但是...

4

2 回答 2

5

这是故意的。当第二个参数由字母和数字组成时,您的 crypt 函数仅使用“salt”的两个第一个字符进行加密,并且这两个字符放置在结果的开头。所以,

crypt("test", "test");        -> teH0wLIpW0gyQ
crypt("test", "te");          -> teH0wLIpW0gyQ
crypt("test", "tea");         -> teH0wLIpW0gyQ
crypt("test", "temperature"); -> teH0wLIpW0gyQ
etc.

这样做是为了方便密码正确性检查,以便
crypt($password, crypt($password, $salt)) == crypt($password, $salt)

于 2013-11-09T21:23:00.950 回答
3

1‍. 我不明白的是我们如何使用两种完全不同的盐获得相同的哈希输出?

尽管您为crypt函数提供了不同的盐,但它在内部使用相同的盐,即te. 这是由于如何crypt实施:

基于 DES 的标准哈希,带有来自字母表“./0-9A-Za-z”的两个字符盐。

因此,即使您提供的盐长度超过 2 个字符,也只需要前两个字符。

并且 ascrypt的输出包含已使用的盐添加到计算的散列中,使用crypt散列作为盐会产生完全相同的输出。这非常完美,因为以下内容可用于验证存储的密码:

crypt($password, $hash) === $hash


2‍. 这是否意味着可能有其他盐可以给我相同的哈希值?

是的。这也适用于其他crypt算法,例如bcrypt

于 2013-11-09T21:27:18.473 回答