【问题标题】:Why string hashed with its hash as salt returns the hash?为什么字符串用它的哈希值作为盐返回哈希值?
【发布时间】:2013-11-21 21:11:34
【问题描述】:

我在阅读 PHP 中的密码安全性时偶然发现了一个有趣的说法:

将密码的哈希值作为盐的哈希值返回相同的哈希值

没有多想,我继续php.net,发现它说的是同样的事情。

我们来看一个例子:

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

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

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

跟进

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

【问题讨论】:

  • 由于鸽巢原理,#2 的答案是肯定的。这几乎会影响基于哈希构建的所有内容,并且在设计良好的系统中不是问题,因为没有输入生成相同的哈希是可以猜测或找出的。
  • #1 的答案是:它取决于加密算法。这个问题没有普遍的答案。我不知道crypt 函数的基本工作原理,但即使我知道,我也怀疑它会是一个简短的答案;-)
  • 一般来说,是的;可能有不止一种盐会给出相同的哈希值,但是对于一个运行良好的网站,这不应该是一个值得关注的主要原因
  • 阅读手册,它都在那里:“基于标准 DES 的哈希,带有来自字母“./0-9A-Za-z”的两个字符盐。”

标签: php security hash passwords


【解决方案1】:

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

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

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

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

并且由于crypt 的输出包含已使用的盐,该盐会附加到计算的散列中,因此使用crypt 散列作为盐会得到完全相同的输出。这很完美,因为可以使用以下内容来验证存储的密码:

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


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

是的。 This does also apply to other crypt algorithms like bcrypt.

【讨论】:

    【解决方案2】:

    这是故意的。当第二个参数由字母和数字组成时,您的 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-01-01
      • 2021-11-19
      • 2011-05-27
      • 2014-11-30
      • 1970-01-01
      • 2015-01-02
      • 2021-06-21
      • 2012-08-13
      • 2017-05-04
      相关资源
      最近更新 更多