PHP password_verify()和慢等于比较

时间:2015-04-07 10:24:42

标签: php security hash

我一直在努力寻找有关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()是否使用长度 - 常数时间比较来避免时间攻击?在文档中没有相关信息,由于我的经验不足,我无法很好地解释函数处理时间结果。

2 个答案:

答案 0 :(得分:8)

答案是肯定它使用长度 - 恒定时间比较。

这是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

处的完整源代码

答案 1 :(得分:4)

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

答案很长:没有必要。

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

$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

现在,对于一个远程攻击者(一个将进行定时攻击的人)来说,盐是一个秘密。当我们重新散列他们的尝试时,盐是相同的。例如:

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

如果攻击者尝试密码&#34; abc&#34;,则内部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减少)。

简而言之,这是件好事,但并非绝对必要......