PHP 5.6引入了hash_equals()
函数,用于安全地比较密码哈希和防止计时攻击。它的签名是:
bool hash_equals(string $known_string, string $user_string)
如文档中所述,$known_string
和$user_string
必须具有相同的长度才能有效防止定时攻击(否则,false
会立即返回,泄漏已知的长度串)。
此外,文档说:
提供用户提供的字符串作为第二个参数非常重要,而不是第一个参数。
这个函数在参数中不对称似乎不直观。
问题是:
以下是该函数源代码的摘录:
PHP_FUNCTION(hash_equals)
{
/* ... */
if (Z_STRLEN_P(known_zval) != Z_STRLEN_P(user_zval)) {
RETURN_FALSE;
}
/* ... */
/* This is security sensitive code. Do not optimize this for speed. */
for (j = 0; j < Z_STRLEN_P(known_zval); j++) {
result |= known_str[j] ^ user_str[j];
}
RETURN_BOOL(0 == result);
}
至于我,关于这两个论点的实现是完全对称的。 可能产生任何影响的唯一操作是XOR运算符。
XOR运算符是否可能在非常量时间内执行,具体取决于参数值?可能它的执行时间取决于参数的顺序(例如,如果第一个参数为零)?
或者是来自PHP的文档&#34;预留&#34;更改未来版本的实施?
正如Morpfh所述,initial proposal implementation不同:
PHP_FUNCTION(hash_compare)
{
/* ... */
/**
* If known_string has a length of 0 we set the length to 1,
* this will cause us to compare all bytes of userString with the null byte which fails
*/
mod_len = MAX(known_len, 1);
/* This is security sensitive code. Do not optimize this for speed. */
result = known_len - user_len;
for (j = 0; j < user_len; j++) {
result |= known_str[j % mod_len] ^ user_str[j];
}
RETURN_BOOL(0 == result);
}
如您所见,草案实现尝试处理不同长度的哈希,并且它不对称地处理参数。也许这个草案实施不是第一个。
总结: 关于参数的文档中的注释&#39;订单似乎是草案实施的剩余部分。
答案 0 :(得分:4)
请参阅RouvenWeßling的评论,(在此答案下面)。
...
这是一个更多的猜测,然后答案,但也许你从中获得了一些东西。
正如你所提到的,有一个猜测是,如果函数经历了未来的变化,可能会向后兼容,因为(1) not 在相等的长度上返回false;因此容易受到泄漏长度信息的影响 - 或者(2)其他算法/检查需要知道哪个是 - 或(n)......
可能的候选人是从提案到实施的剩余部分:
因此,来自 Proposal 的人有:
用户必须注意,因为用户提供的字符串(或该字符串的散列)用作第二个参数而不是第一个参数非常重要。
自创建提案以来,这已经存在:
可以链接到参考,例如:
其中一个不返回相同的长度,但循环useLen。