【问题标题】:PHP password_hash() / bcryptPHP password_hash() / bcrypt
【发布时间】:2015-06-07 00:46:18
【问题描述】:

我正在检查 bcrypt 哈希算法。

我第一次使用 password_hash() 测试:

echo password_hash("123", PASSWORD_BCRYPT, array( "salt" => "1234567890123456789012" ));
echo password_hash("123", PASSWORD_BCRYPT, array( "salt" => "1234567890123456789012xxxxxxxxxxxxxxx" ));

两者都将返回“$2y$10$123456789012345678901uiaLpJxTpf6VbfI5NADlsRsfvEm6aq9C”。

  1. 为什么盐存储在哈希中?这对我来说完全没有意义。从数据库中获取哈希值的攻击者如果不知道盐值,就无法对它们进行任何操作。
  2. 为什么使用两种不同的盐得到相同的哈希?是否只有前 22 个字符用于传递给函数的盐?

非常感谢!

【问题讨论】:

    标签: php hash bcrypt


    【解决方案1】:

    盐不是秘密,它通常与哈希一起存储在数据库中,也可以像password_hash 那样直接存储在哈希中。

    盐创造了唯一性,因此散列不容易被彩虹表或字典之类的东西破解,除了使散列更加独特之外,它并没有真正增加安全性,因此针对散列运行字典或表不会匹配,因为它还包括盐。

    如果省略盐,password_hash() 将为每个散列密码生成一个随机盐。这是预期的操作模式,您不应提供自己的盐。
    PHP7 实际上会产生一个警告,告诉您不推荐使用 salt 选项。

    传递的盐至少需要 22 个字符,但大多数底层算法,如 bcrypt,不使用整个盐,请参阅 this answer 了解更多信息

    【讨论】:

    • 感谢您和其他人的回复!我确实了解盐的工作原理。目前我使用的是 SHA256,作为 Salt,我使用很长的 Salt(硬编码在配置 PHP 文件中)+ UserID,因此,当两个用户具有相同的密码时,他们将具有不同的密码哈希。我仍然认为让盐“秘密”,安全性增加了很多。如果用户有 8 个字符的密码,我不需要彩虹表,我可以非常快速地对其进行暴力破解。但如果我不知道盐,我什么都做不了。
    • 当然,暴力破解 bcrypt 是另一回事……我只是想到了这一点。
    • 好吧,这取决于您,如果您认为将盐保密会大大提高您的安全性,那就保密吧,这肯定不会有什么坏处,但我们基本上是在告诉您也无所谓。如果有人可以访问存储的哈希,他们可能仍然可以访问配置中的用户 ID 和存储的盐,这就是为什么盐应该是每个哈希的唯一字符串,这使得运行变得更加困难当您必须为每个哈希添加唯一的盐时,针对字典的整个哈希列表。
    • "目前我正在使用 SHA256" 不好。 “作为Salt,我使用了很长的Salt(硬编码在配置PHP文件中)”不好。文档明确警告不要这样做。 “如果用户有 8 个字符的密码,我不需要彩虹表,我可以非常快速地对其进行暴力破解” 不使用 bcrypt,你不能。您应该调整 bcrypt,以便散列密码大约需要 0.1 秒。 8 个字符的密码有 3,025,989,069,143,040 种可能的组合,这意味着暴力破解需要 数千年
    【解决方案2】:

    盐不是你必须努力保守秘密的东西。即使已知,它们的保护也是有效的。 https://crackstation.net/hashing-security.htm

    盐不需要保密。仅仅通过随机化哈希,查找表、反向查找表和彩虹表就变得无效了。攻击者不会事先知道盐是什么,因此他们无法预先计算查找表或彩虹表。如果每个用户的密码使用不同的盐进行哈希处理,反向查找表攻击也不会起作用。

    由于您似乎使用的是固定盐值,请注意这一点:

    一个常见的错误是在每个哈希中使用相同的盐。盐要么被硬编码到程序中,要么随机生成一次。这是无效的,因为如果两个用户有相同的密码,他们仍然有相同的哈希值。攻击者仍然可以使用反向查找表攻击同时对每个散列进行字典攻击。他们只需要在对密码进行散列之前将盐应用于每个密码猜测。如果盐被硬编码到流行产品中,则可以为该盐构建查找表和彩虹表,以便更容易破解产品生成的哈希。

    我建议使用不带可选参数的password_hash。默认功能的构建是高度安全的,通过指定您自己的算法和选项,您可能会削弱其功能。

    根据PHP documentation

    注意 强烈建议您不要为此函数生成自己的盐。如果您不指定,它将自动为您创建一个安全的盐。

    编辑:这就是为什么在 bcrypt 中保密盐是没有意义的。

    根据this post,8 个字符的密码有 3,025,989,069,143,040 种可能的组合。您通常应该将 bcrypt 的工作因子调整为花费 0.1 秒来散列密码。这意味着计算所有可能性需要 302,598,906,914,304 秒。那是 9,588 千年

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-31
      • 1970-01-01
      • 2016-12-09
      • 2019-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多