c — Почему важен порядок аргументов в функции 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 выполняется в непостоянное время, в зависимости от значений аргумента? Может ли время его выполнения зависеть от порядка аргументов (например, если 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);
}

Как вы видите, черновая реализация пыталась обрабатывать хэши разной длины, и аргументы обрабатывались асимметрично. Возможно, этот проект реализации не первый.

Подводя итог: примечание в документации о порядке аргументов, похоже, осталось от черновика реализации.

11

Решение

Обновить:

Смотрите комментарий от Rouven Weßling, (ниже этого ответа).


Это скорее спекуляция, чем ответ, но, возможно, вы получите что-то из этого.


Одна из догадок, как вы упомянули, состоит в том, что для вероятной обратной совместимости функция подвергнется будущему изменению по какой-либо причине (1) не вернуть false на равную длину; таким образом, будучи уязвимым для информации о длине утечки — или (2) других алгоритмов / проверок, где нужно знать, что есть что — или (n) …


Вероятный кандидат — то, что это — остаток от предложения до реализации:

Как таковой, из Предложение один имеет:

Пользователи должны быть внимательны, так как важно, чтобы введенная пользователем строка (или хэш этой строки) использовалась в качестве второго параметра, а не первого.

Это присутствует с момента создания предложения:

Который может быть связан с Рекомендации, например:

где делать не возврат на равную длину, но цикл useLen.

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]