Почему PHP crypt() добавляет соль в хеш?
Я смотрю на создание системы входа в систему и после прочтения руководства по PHP, когда вы передаете 2-значный соли в crypt()
Функция возвращает строку хеша, и первые 2 цифры строки - это соль, которую вы использовали.
пример:
$salt = "kr";
echo crypt("mysecret",$salt); //returns "kreOI.F7eOQMY"
Моя первая мысль была, не поможет ли это кому-то, кто пытается перевернуть твой хэш?
Я посмотрел соль в Википедии, которая сказала:
Для лучшей безопасности значение соли держится в секрете.
Так что я не понимаю, почему тогда функция crypt будет возвращать все хэши с добавленным значением соли?
Для этого есть причина? Должно ли это быть проблемой безопасности?
6 ответов
Функция crypt() устарела. Он использовался для хэширования паролей для систем Unix старого стиля, до того как появилась поддержка теневых паролей. Соль была там, чтобы увеличить сложность взлома пароля. Однако, так как соль была случайным образом сгенерирована подсистемой паролей, ее необходимо было хранить в открытом виде, чтобы любые будущие действия с паролями работали. Если бы соль была встроена в пароль до шифрования, то не было бы никакого практического способа проверить пароль - вы должны были бы попробовать каждую возможную соль, когда была сделана проверка пароля - очень непрактично. Итак, соль была добавлена к зашифрованному паролю, чтобы вы могли снова извлечь его для дальнейшего использования.
crypted password: xxabcdefghijklmn
^^- salt
^^^^^^^^^^^^^^-- crypted pw
if ('xx' + crypt('xx' + password) == 'crypted string') then
password is ok
endif
В наши дни crypt() является безопасным эквивалентом кольца декодера зерновых. Там в исторических целях и с низким уровнем безопасности "кто заботится, если он взломан" хранилище. Для любого современного использования пароля вам лучше использовать более современные хеши, такие как sha1/sha256/md5. И даже md5 в наши дни считается сломанным, sha1 имеет трещины по краям, и (последний раз я проверял) sha256 по-прежнему безопасен.
Автор статьи в Википедии совмещает соль с идеей пространства поиска, подразумевая, что соль - это способ сдерживать атаки методом грубой силы. Безопасность не улучшается, путая эти идеи; кто-то, кто не может распознать и разграничить эти две проблемы, не заслуживает доверия.
Цель соли - помешать предварительно вычисленным таблицам поиска (например, таблица Радуга). Соль мешает атакующему обменять "пространство" на "время". Каждый кусочек соли удваивает требования к хранению стола; двухбайтовая соль имеет большое значение (65536 раз), но для восьми байтов потребуются несуществующие "йоттабайтные" устройства хранения для справочных таблиц.
Соль должна храниться где-то. Если у вас был эффективный способ сохранить "секрет", почему бы не использовать его для хранения пароля и вообще забыть о хешировании? Нет; если вам нужна реальная безопасность, вы должны спроектировать систему защищенной от атаки методом перебора, даже если злоумышленник знает, что такое соль. Предположение статьи о том, что соль может храниться в секрете, должно рассматриваться как ложное.
Атаки грубой силой лучше всего предотвращаются усилением ключа (применяя хэш-функцию тысячи раз) и правилами выбора пароля (минимальная длина, цифры, специальные символы).
Предположение, что соль не может храниться в секрете, способствует лучшему усилению ключа и выбору пароля, и это приводит к более безопасной системе.
Я должен прокомментировать, что Crypt не так плох, как это делает Марк Б, и на самом деле может быть самым простым способом получить хорошие хэши, если вы не полагаетесь на его более слабые схемы, такие как MD5.
Увидеть:
Как вы используете bcrypt для хеширования паролей в PHP?
Да, соль должна храниться в секрете, но так же и хеш пароля. Для них вполне приемлемо хранить одинаково секретно в одном и том же месте. Чтобы проверить пароль по хешу, вам нужно объединить соль с паролем, а затем проверить его по хешу. Таким образом, любой пользователь или процесс, имеющий право на просмотр хэша пароля, также должен иметь право на просмотр соли, поскольку хэш пароля сам по себе бесполезен для проверки паролей (если только вы не собираетесь перебирать соль).
Соль в том, что если два разных пользователя имеют один и тот же пароль, они будут хэшировать разные вещи. Это также означает, что атаки по словарю намного сложнее, потому что вы не можете просто хэшировать все вероятные пароли, а затем проверять их по списку хешей паролей пользователей, чтобы найти пароли нескольких пользователей. Вместо этого вы должны попробовать пароли для отдельной соли, чтобы найти пароль одного пользователя, или попробовать все комбинации вероятных паролей с несколькими солями, чтобы найти совпадения. Но знание соли само по себе не означает, что вы можете изменить хеш пароля. Это просто означает, что вы можете провести атаку по словарю на хеш пароля.
Если вы можете найти способ сохранить соль более защищенной, чем хеш-значение, это, конечно, не будет плохой вещью, но трудно понять, как это возможно, когда любая программа, которой нужен доступ к одному, нуждается в доступе к обоим.
PHP crypt наследует это поведение от UNIX crypt()
функция, которая использовалась для генерации хэшей паролей в UNIX passwd
файл. Нужно где-то хранить соль, иначе вы не сможете проверить правильность пароля. Для passwd
Файл, простое поведение было просто добавить соль (всегда два символа) к началу зашифрованного пароля, что позволяет легко хранить его в одном поле.
Утверждение о том, что значение соли должно храниться в секрете, может быть неверно истолковано. Для лучшей практики не следует публиковать свои соли так же, как вы не должны публиковать хэши паролей. Предоставление злоумышленнику хешей и солей облегчает им запуск атаки грубой силы, не вызывая подозрительный трафик в вашей системе. Тем не менее, система все еще должна быть защищена, даже если злоумышленник может видеть как солевой, так и хешированный пароль.
Фактически, вы нигде не можете хранить хэш, который, в принципе, не может быть скомпрометирован хакером точно так же, как хешированные пароли. Если код проверки пароля может получить к нему доступ, то вы должны предположить, что тот, кто скомпрометировал систему, также может получить к ней доступ.
Соль добавляется к значению, так что вы узнаете, какую соль использовать, когда получите пароль и захотите проверить, соответствует ли он хешу. Идея здесь состоит в том, чтобы использовать разные соли для каждого пароля, чтобы кто-то не мог предварительно вычислить хеш-таблицу.
Вы также можете добавить вторую соль к каждому паролю (одинаковую для всех) и никому не говорить, что это такое.