Я использую crypt()
для хэш-паролей в PHP и пытаюсь разработать самый безопасный способ проверки равенства получающегося хэша при выполнении проверок пароля.
Я вижу три варианта:
Вариант 1 – Double Equals
function checkPassword($hash, $password) { return crypt($password, $hash) == $hash; }
Вариант 2 – Triple Equals
function checkPassword($hash, $password) { return crypt($password, $hash) === $hash; }
Вариант 3 – strcmp()
function checkPassword($hash, $password) { return strcmp(crypt($password, $hash), $hash) === 0; }
Моя интуиция подсказывает мне, что вариант 1 – плохая идея из-за отсутствия проверки типа, и что варианты 2 или 3, вероятно, будут лучше. Тем не менее, я не могу разобраться, есть ли какой-то конкретный случай, из-за которого strcmp
ошибка ===
или strcmp
. Что безопаснее для этой цели?
Когда дело доходит до безопасности, я предпочитаю использовать оператор ===
. ===
гарантирует, что два операнда будут точно такими же, не пытаясь приспособить кастинг, чтобы «помочь» сравнению для достижения успешного совпадения, поскольку это может помочь во время разработки благодаря свободному типу языка, например PHP.
Конечно, одному из операндов нужно доверять. Хэш из базы данных является надежным, а пользовательский ввод – нет.
Некоторое время можно сглазить, придя к выводу, что в конкретном случае нет риска использовать ==
. Может быть. Но, например
"0afd9f7b678fdefca" == 0 is true "aafd9f7b678fdefca" == 0 is also true
поскольку PHP пытается преобразовать «хеш» в число (возможно, используя atoi ), которое дает 0. Хотя маловероятно, что crypt
возвращает 0, я бы предпочел максимизировать случаи, когда пароли не совпадают (и ответ на вызов поддержки ), используя ===
, чем разрешить редкий случай, о котором я не думал, используя ==
.
Что касается strcmp
, функция возвращает <0
или >0
если они разные, и 0, если они равны. Но
strcmp("3", 0003) returns 0 strcmp("0003", 0003) returns -3
что неудивительно в конце концов. Литерал 0003
на самом деле является целым числом 3
и поскольку strcmp ожидает строку, 3
будет преобразована в "3"
. Но это показывает, что в этом случае может произойти некоторая конверсия, поскольку strcmp является функцией, а ===
является частью языка.
Поэтому мое предпочтение в этом случае идет на ===
(что быстрее, чем ==
любом случае).
Вы должны использовать функцию hash_equals (), встроенную в PHP. Не было бы необходимости создавать свою собственную функцию. Функция hash_equals () вернет логическое значение.
По-моему, обычно не рекомендуется использовать == или === для сравнения строк, не говоря уже о хэшированных строках.
Это неверно, посмотрите на определение функции. Согласно PHP:
Returns < 0 if str1 is less than str2;
> 0 if str1 is greater than str2,
and 0 if they are equal
Он возвращает меньше 0, если str1 меньше str2. Обратите внимание на фразу «меньше», она не возвращает только -1, но любое отрицательное значение. То же самое происходит, когда str1 больше str2, но возвращает положительное, ненулевое значение. Он возвращает положительное значение, которое может быть 1 или любое число после этого.
strcmp()
возвращает число, которое является разницей между двумя строками, начиная с последнего символа, который был признан похожим.
Вот пример:
$output = strcmp("red", "blue");
Вывод переменной $ output содержит значение 16
Я думаю, что использование ==
будет достаточным в вашем случае.
==
проверяет равенство независимо от типа, тогда как ===
проверяет равенство, а также тип.
1 == "1"
= True
1 === "1"
= False
Поскольку мы не слишком обеспокоены типом, я бы сохранил его простым и перешел с ==
.