Почему порядок аргументов в функции PHP hash_equals() важен?
В 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, первоначальная реализация была другой:
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
Обновление:
См. комментарий от Рувена Васлинга (ниже этого ответа).
...
Это скорее размышление, чем ответ, но, возможно, вы получите что-то из этого.
Предполагается, что, по вашему мнению, существует вероятность обратной совместимости, если функция претерпевает изменения в будущем, по какой-либо причине, чтобы (1) не возвращать false на равной длине; таким образом, будучи уязвимым для информации о длине утечки - или (2) других алгоритмов/проверок, где нужно знать, что является - или (n)...
Вероятным кандидатом является то, что он остается от предложения к реализации:
Таким образом, из предложения одно:
Пользователи должны помнить о том, что важно, чтобы пользовательская строка (или хэш этой строки) использовалась как второй параметр, а не первый.
Это присутствует с момента создания предложения:
Что может быть связано с ссылками, например:
где один не возвращается на равной длине, но loop useLen.