【发布时间】:2015-03-10 18:52:33
【问题描述】:
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 文档中的这个注释是对未来版本中实现更改的“保留”?
编辑
正如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);
}
如您所见,草案实现尝试处理不同长度的哈希,并且不对称地处理参数。也许这个实施草案不是第一个。
总结: 文档中关于参数顺序的注释似乎是实施草案的遗留物。
【问题讨论】:
-
当文档告诉你这样的事情并且没有解释原因时,我总是讨厌它。
-
1) 这是一个 PHP 问题,为什么用 'c' 标记 2) 参数必须按特定顺序排列,因为这是函数期望参数的方式。
-
@user3629249, 1) 它被标记为 C 因为 PHP 是用 C 实现的,它更多的是关于 PHP 的实现而不是使用。 2) 抱歉,我无法在您的最后陈述中找到任何信息。
-
合约应该按价值计算。尊重它。
-
@user2864740:+1,我愿意!这个问题没有实用价值,纯粹是好奇。
标签: php c security php-internals timing-attack