#laravel #hash #bcrypt
#laravel #хэш #bcrypt
Вопрос:
Я наблюдал очень странное поведение с использованием Hash
фасада Laravel Hash::make()
для создания дайджеста (с bcrypt
) и сохранения его в базе данных. Например, обычный текст
AAMkAGEzN2EyZTg4LWRiNTUtNGIwYS04ZTA1LWE2Y2U5OTRjYjQ0ZgBGAAAAAACxCzc14g3eSoadAxaGpB3ABwCr5qkyxHH4QY9vHKr6u5IrAAAAAAENAACr5qkyxHH4QY9vHKr6u5IrAARi2BmGAAA=
выдает $2y$10$fq6jvoNL/RShVKfNDy64EOGW0gLzd0GvfS.di16Z9LcCK7DpIHONK
результат .
Теперь, при использовании Hash::check()
с обычным текстом и дайджестом, упомянутым выше, возвращает true
, конечно. Однако изменение одного символа в обычном тексте (например, замена последнего A
на a B
) и проверка его на соответствие тому же дайджесту true
также возвращает:
>>> Hash::check('AAMkAGEzN2EyZTg4LWRiNTUtNGIwYS04ZTA1LWE2Y2U5OTRjYjQ0ZgBGAAAAAACxCzc14g3eSoadAxaGpB3ABwCr5qkyxHH4QY9vHKr6u5IrAAAAAAENAACr5qkyxHH4QY9vHKr6u5IrAARi2BmGAAA=', '$2y$10$fq6jvoNL/RShVKfNDy64EOGW0gLzd0GvfS.di16Z9LcCK7DpIHONK')
=> true
>>> Hash::check('AAMkAGEzN2EyZTg4LWRiNTUtNGIwYS04ZTA1LWE2Y2U5OTRjYjQ0ZgBGAAAAAACxCzc14g3eSoadAxaGpB3ABwCr5qkyxHH4QY9vHKr6u5IrAAAAAAENAACr5qkyxHH4QY9vHKr6u5IrAARi2BmGAAB=', '$2y$10$fq6jvoNL/RShVKfNDy64EOGW0gLzd0GvfS.di16Z9LcCK7DpIHONK')
=> true
>>> Hash::check('AAMkAGEzN2EyZTg4LWRiNTUtNGIwYS04ZTA1LWE2Y2U5OTRjYjQ0ZgBGAAAAAACxCzc14g3eSoadAxaGpB3ABwCr5qkyxHH4QY9vHKr6u5IrAAAAAAENAACr5qkyxHH4QY9vHKr6u5IrAARi2BmGAAC=', '$2y$10$fq6jvoNL/RShVKfNDy64EOGW0gLzd0GvfS.di16Z9LcCK7DpIHONK')
=> true
Исходя из моего понимания того, что делает хеширование, это не должно быть возможным, но, похоже, это не коллизия, поскольку замена B
на C
также приводит true
.
Я использую Laravel 8.0 с PHP 7.4.11.
Есть идеи, что я здесь делаю не так?
ОБНОВЛЕНИЕ: нашел эту подсказку в официальной документации PHP для password_hash
:
Внимание: Использование PASSWORD_BCRYPT в качестве алгоритма приведет к усечению параметра пароля до максимальной длины 72 символов.
Затем я проверил это, и действительно, изменение любого из символов позади AAMkAGEzN2EyZTg4LWRiNTUtNGIwYS04ZTA1LWE2Y2U5OTRjYjQ0ZgBGAAAAAACxCzc14g3e
не меняет результат при замене, например, последнего e
на f
returns false
for Hash::check()
. Длина строки — это 72
символы, поэтому это может быть результатом усечения. Но почему?Это не упоминается в Hash
документации Laravel. У меня есть несколько паролей длиной более 72 символов, так что на самом деле не имеет значения, как они заканчиваются?
В результате мне нужно использовать другую функцию Laravel для хэширования более длинных сообщений? Какое из них?
Ответ №1:
Я провел некоторое исследование и пришел к такому выводу:
В официальных документах laravel они ссылаются на официальные документы php. Здесь у них есть caution
раздел, в password
котором говорится:
Использование PASSWORD_BCRYPT в качестве алгоритма приведет к тому, что параметр пароля будет усечен до максимальной длины 72 символов.
Я проверил вашу строку, и она имеет длину 152. Поэтому в вашем случае вам следует использовать другой алгоритм (вы можете установить это в config/hashing.php
at driver
) или убедиться, что входная строка содержит не более 72 символов.
Комментарии:
1. Спасибо. Это согласуется с моими выводами, которые я добавил в вопросе. Знаете ли вы, в чем причина такого решения?
2. Я немного огляделся, и я не могу найти, почему это 72. Но в целом существуют ограничения для ограничения функциональности, чтобы это не занимало много времени или не переполняло память.
3. Для меня это имеет смысл для
password_hash
функции, но не дляHash
фасада, поскольку хэш-функции используются не только для хеширования паролей. По крайней мере, намек в документации был бы хорош, иначе произойдет много столкновений. Я добавил примечание для этого в Laravel docs GitHub , надеюсь, оно будет извлечено и поможет другим разработчикам не тратить столько времени на отладку … : D4. Я имею в виду, что документы laravel ссылаются на документы php. Таким образом, они приводят вас к правильной информации, вам просто нужно самостоятельно найти информацию, как и в большинстве документов по программированию. Если в каждом документе нужно перечислять каждое требование, это станет адом для обслуживания, поскольку каждый должен обновлять одно и то же изменение в своих документах.
5. Смотрите первую часть этого ответа , почему существует эта проблема. @Johannes