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);
}
Как вы видите, черновая реализация пыталась обрабатывать хэши разной длины, и аргументы обрабатывались асимметрично. Возможно, этот проект реализации не первый.
Подводя итог: примечание в документации о порядке аргументов, похоже, осталось от черновика реализации.
Смотрите комментарий от Rouven Weßling, (ниже этого ответа).
…
Это скорее спекуляция, чем ответ, но, возможно, вы получите что-то из этого.
Одна из догадок, как вы упомянули, состоит в том, что для вероятной обратной совместимости функция подвергнется будущему изменению по какой-либо причине (1) не вернуть false на равную длину; таким образом, будучи уязвимым для информации о длине утечки — или (2) других алгоритмов / проверок, где нужно знать, что есть что — или (n) …
Вероятный кандидат — то, что это — остаток от предложения до реализации:
Как таковой, из Предложение один имеет:
Пользователи должны быть внимательны, так как важно, чтобы введенная пользователем строка (или хэш этой строки) использовалась в качестве второго параметра, а не первого.
Это присутствует с момента создания предложения:
Который может быть связан с Рекомендации, например:
где делать не возврат на равную длину, но цикл useLen.
Других решений пока нет …