为什么字符串散列哈希值为哈希返回哈希?

Zor*_*leQ 6 php security passwords hash

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

使用散列散列密码作为salt返回相同的散列

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

我们来看一个例子:

crypt("test", "test"); -> teH0wLIpW0gyQ
crypt("test", "teH0wLIpW0gyQ"); -> teH0wLIpW0gyQ
Run Code Online (Sandbox Code Playgroud)

我完全可以理解PHP中的crypt会生成给定字符串的单向散列.

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

跟进

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

Ser*_*nko 5

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

crypt("test", "test");        -> teH0wLIpW0gyQ
crypt("test", "te");          -> teH0wLIpW0gyQ
crypt("test", "tea");         -> teH0wLIpW0gyQ
crypt("test", "temperature"); -> teH0wLIpW0gyQ
etc.
Run Code Online (Sandbox Code Playgroud)

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


Gum*_*mbo 3

\n

1\xe2\x80\x8d。我不明白的是我们如何使用两种完全不同的盐获得相同的哈希输出?

\n
\n\n

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

\n\n
\n

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

\n
\n\n

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

\n\n

由于crypt\xe2\x80\x99s 输出包含在计算的哈希值之前使用的盐,因此使用crypt哈希值作为盐会产生完全相同的输出。\xe2\x80\x99s 非常完美,因为可以使用以下内容来验证存储的密码:

\n\n
crypt($password, $hash) === $hash\n
Run Code Online (Sandbox Code Playgroud)\n\n


\n\n
\n

2\xe2\x80\x8d。这是否意味着可能有其他盐可以给我相同的哈希值?

\n
\n\n

是的。这也适用于bcryptcrypt等其他算法。

\n