【问题标题】:PHP password_verify() and slow equals comparisonPHP password_verify() 和慢等于比较
【发布时间】:2015-04-07 10:24:41
【问题描述】:

我一直在尝试查找有关password_verify() 是否使用长度常数时间比较来避免定时攻击的信息。

现在,简单的例子:

$hash = '$2y$10$HH3906lfby7HOy1N3duQh.Kju.84ct6AcMZm2p/SYZsZSXuYWvvT.';

$startTime = microtime(TRUE);
password_verify('rasmuslerdorf', $hash);
$endTime = microtime(TRUE);

$time = $endTime - $startTime;

这总是会产生略有不同的输出,根据this article“为什么此页面上的哈希代码会比较“长度恒定”时间段中的哈希?”),可以用于定时攻击以获取哈希。我认为这些结果看起来有点随机,但它们肯定不是恒定的。

问题是password_verify() 是否使用长度常数时间比较来避免定时攻击?文档中没有关于它的信息,由于我的经验浅薄,我无法很好地解释函数处理时间结果。

【问题讨论】:

    标签: php security hash


    【解决方案1】:

    答案是肯定的,它使用长度常数时间比较。

    这是php的password_verify函数的摘录

        /* We're using this method instead of == in order to provide
     * resistance towards timing attacks. This is a constant time
     * equality check that will always check every byte of both
     * values. */
    for (i = 0; i < hash_len; i++) {
        status |= (ret->val[i] ^ hash[i]);
    }
    

    您可以在https://github.com/php/php-src/blob/master/ext/standard/password.c查看完整的源代码

    【讨论】:

      【解决方案2】:

      简短回答:是的,确实如此。

      长答案:没必要。

      要了解为什么没有必要,我们需要查看正在比较的字符串:

      $2y$10$9JxHB8U1QKsLS/ynplKzm.iIO7f6gtTKYA61ppVuANYxWNCA5DW1S
      $2y$10$ILlWQrYyDJvHHkxcCgjm7OThLRAmMcTzsJOZOwjaSYiRUHq8LVYde
      $2y$10$8JfydDKUNbOeiybwZ9m.j.5TC8CBqkc3RZu2DX42A4dFNpNYPWfzm
      $2y$10$qeG.53lr9PVVGN4Yk.kSZuOMpfone5kINyWVpAf2gUXPseU2WdSzK
      $2y$10$nZUgPUwiXIvCJ9BY1wbtbuV5vH6yff9CNyumFsI/NN2eJmf20iec.
      

      这是相同密码的 5 个不同哈希值。格式为:

      $2y$10$saltsaltsaltsaltsaltsahashhashhashhashhashhashhashhas
      

      现在,对于远程攻击者(将运行定时攻击的人)来说,salt 是一个秘密。当我们重新哈希他们的尝试时,盐是一样的。例如:

      stored password "test":
      hash = $2y$10$9JxHB8U1QKsLS/ynplKzm.iIO7f6gtTKYA61ppVuANYxWNCA5DW1S
      

      如果攻击者尝试密码“abc”,内部password_verify() 将调用crypt("abc", hash)。这将导致:

      $2y$10$9JxHB8U1QKsLS/ynplKzm.FTYpGS/gNDw4SB6YD0wEtCSPgGvtPim
      

      现在,让我们并排看一下这两个哈希:

      $2y$10$9JxHB8U1QKsLS/ynplKzm.iIO7f6gtTKYA61ppVuANYxWNCA5DW1S
      $2y$10$9JxHB8U1QKsLS/ynplKzm.FTYpGS/gNDw4SB6YD0wEtCSPgGvtPim
      

      注意盐是一样的吗?请注意,直到第一个 . 之前的所有内容都是相同的。另请注意,攻击者不知道盐是什么。

      如果攻击者能够对比较进行定时攻击,那就没有用了。因为他们不知道盐(因此推断哈希是什么只是浪费时间,因为没有盐他们无法确定密码)。

      所以时间安全并不是绝对必要的。

      那为什么要包含它呢?因为每个人都会犯错。因为纵深防御是个好主意。因为这个分析假设没有盐,散列没有任何用处(例如:如果 bcrypt 中的缺陷使散列基于密码产生偏差,所以在不知道盐的情况下,密钥空间从 72^255 减少)。

      简而言之,拥有它是一件好事,但并非绝对必要......

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-05-16
        • 2020-05-10
        • 2018-04-17
        • 1970-01-01
        • 2022-07-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多