В 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 выполняется за непостоянное время в зависимости от значений аргументов? Может ли время его выполнения зависеть от порядка аргументов (например, если 1-й аргумент равен нулю)?
Или это примечание из документации PHP является «оговоркой» для изменений реализации в будущих версиях?
Редактировать
Как указано в Morpfh, первоначальная реализация предложения была другой:
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);
}
Как вы видите, черновик реализации пытался обрабатывать хэши разной длины и обрабатывал аргументы асимметрично. Возможно, эта черновая реализация не первая.
Подводя итоги: примечание в документации о порядке аргументов кажется пережитком черновой реализации.