я использую password_hash
для шифрования пароля. Однако есть странный вопрос, password_hash
стоить очень долго. Вот пример кода.
этот код будет стоить более 1 секунды. Это нормально?
<?php
$startTime = microtime(TRUE);
$password='123456';
$cost=13;
$hash=password_hash($password, PASSWORD_DEFAULT, ['cost' => $cost]);
password_verify($password,$hash);
$endTime = microtime(TRUE);
$time = $endTime - $startTime;
echo $time;
?>
Результат: 1.0858609676361
После запуска на 3v4l это кажется совершенно нормальным.
Хеширование паролей — это не то, что вы хотите оптимизировать. Словами Ли на hash
документация:
Если вы хешируете пароли и т. Д. Для безопасности, скорость не ваш друг. Вы должны использовать самый медленный метод.
Медленное хэширование означает медленное взламывание и, мы надеемся, создаст такие вещи, как радужные таблицы, больше проблем, чем оно того стоит.
Алгоритм по умолчанию для password_hash
, bcrypt
, является предназначенный быть медленным
http://en.wikipedia.org/wiki/Key_stretching
В криптографии растяжение ключа относится к методам, используемым для создания, возможно, слабого ключа, обычно пароля или ключевой фразы, более защищенного от атаки методом подбора, увеличивая время, необходимое для тестирования каждого возможного ключа. Пароли или парольные фразы, созданные людьми, часто бывают короткими или достаточно предсказуемыми для взлома паролей. Растяжение ключа делает такие атаки более сложными.
http://en.wikipedia.org/wiki/Rainbow_table#Defense_against_rainbow_tables
Еще одна техника, которая помогает предотвратить атаки до вычислений, — это растяжение ключа. При использовании растяжения соль, пароль и ряд промежуточных хеш-значений запускаются через базовую хеш-функцию несколько раз, чтобы увеличить время вычисления, необходимое для хеширования каждого пароля. Например, MD5-Crypt использует итерационный цикл 1000, который многократно возвращает соль, пароль и текущее промежуточное хеш-значение обратно в базовую хеш-функцию MD5. Хэш пароля пользователя представляет собой объединение значения соли (что не является секретным) и окончательного хэша. Дополнительное время не заметно для пользователей, потому что им приходится ждать лишь доли секунды при каждом входе в систему. С другой стороны, растяжение снижает эффективность атак методом «грубой силы» пропорционально количеству итераций, поскольку оно уменьшает количество вычислений, которые злоумышленник может выполнить за данный период времени. Этот принцип применяется в MD5-Crypt и в bcrypt. Это также значительно увеличивает время, необходимое для построения предварительно вычисленной таблицы, но в отсутствие соли это нужно сделать только один раз.
Полная секунда, вероятно, немного длинна — вы можете поэкспериментировать с падением $cost
на один или два, чтобы приблизить его к доле секунды, что сохранит эффективную защиту, оставляя задержку незаметной для ваших пользователей.
Да, это нормально. Вот что cost
Параметр предназначен для: он позволяет настроить счетчик итераций, делая хэш медленнее или быстрее по мере необходимости.
Вы должны всегда делать хэш как можно медленнее и быстрее, если это необходимо. Причина в том, что единственно возможной атакой на хеш пароля является грубая сила. Вы хотите, чтобы стоимость была настолько большой, что для простого перебора всех возможных значений требуется слишком много времени. Это ваша единственная реальная защита от злоумышленников с хэшированием паролей.
Одна целая секунда кажется непозволительно для вашего собственного использования. Вы должны немного снизить эту стоимость, чтобы не превышать нескольких сотен миллисекунд. Приспособьтесь к своим целевым системам по мере необходимости.
Начать, password_hash
это не шифрование.
password_hash () создает новый хэш пароля, используя сильный односторонний алгоритм хеширования. password_hash () совместим с crypt (). Следовательно, хеши паролей, созданные crypt (), могут использоваться с password_hash ().
Хеш является односторонним, и что бы вы ни передавали, оно всегда будет иметь одинаковый конечный результат, однако вы не сможете получить исходную строку из хеша. Это идеально подходит для паролей, потому что вы хотите хранить обфусцированную версию пароля пользователя, которую вы можете легко сравнить при входе в систему без фактического сохранения пароля. Это означает, что если база данных взломана, пока пароли были хешированы, злоумышленник не получит пароли, он получит хешированные пароли, которые по сути бесполезны (вы можете использовать радужные таблицы, и я уверен, что другие методы, чтобы получить Получаются хэши, но это требует приличного количества усилий).
Это приводит к вашему первоначальному вопросу. Почему хеши паролей медленные? Они медленные, потому что единственный способ получить исходную строку из хеша — это заново сгенерировать этот хеш. Таким образом, если генерация каждого хэша занимает 1 секунду, он становится больше времени, чем если бы вы использовали быстрый хеш, такой как md5
версии sha
, Быстрые хеши отлично подходят практически для всего, кроме хранения паролей.
Надеюсь, это ответит на ваш вопрос. Кроме того, я настоятельно рекомендую генерировать уникальную соль для каждого пользователя и передавать ее в качестве одного из вариантов в password_hash
, Эта соль может храниться в виде простого текста в базе данных вместе с хешированным паролем. Использование различной соли для каждого пароля добавит это в пароль, так что потенциальный злоумышленник должен будет создать радужную таблицу для каждой соли, которая находится в базе данных. На этом этапе злоумышленник, вероятно, будет использовать другие методы для получения паролей вместо взлома базы данных.