Как шифровать пароли php

PHP – всё про защиту пароля

Сейчас множество сайтов требуют авторизацию, используя в качестве логина email, и реже – телефон. Но как хранится ваш пароль в базе данных? Действительно ли это безопасно и может ли владелец сайта воспользоваться этими данными? Давайте разбираться.

PHP – md5 вычисляем хеш строки

Строки? А почему не пароля?
НЕ ИСПОЛЬЗУЙТЕ md5 для “шифрования” паролей, это очень ненадежное средство. Как это выглядит на практике:

echo md5('test123'); // cc03e747a6afbbcbf8be7668acfebee5 echo md5('test124'); // ad2af2578b4d55b5f78383024270f852

Если запустить данную команду, то функция вернёт MD5-хеш строки. У нас два разных пароля, у которых отличается только последний символ test123 и test124. Разница 1 символ, но ничего общего в хеше md5 нет.

Так почему же такой способ ненадежный? Он очень легко ломается, и если вы не можете перевести обратно из md5 в текст, то для злоумышленника это не займет много времени (что уж там говорить, если есть сайты, которые это делают в пару кликов).

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

$passwordHash = ‘cc03e747a6afbbcbf8be7668acfebee5’; $password = $_REQUEST[‘password’]; if (md5($password) === $passwordHash) < echo 'done'; >else

Где, $passwordHash – это зашифрованный пароль, который лежит в базе данных, а $password = $_REQUEST[‘password’] – это пароль, который ввел пользователь через форму авторизации.

Читайте также:  Javascript buttons and functions

PHP – Как надежно защитить пароль?

Для этого нам понадобится функция password_hash и password_verify. Как вообще должен храниться пароль:

При таком указании пароля он делится на части:
алгоритм – при помощи которого и был зашифрован пароль;
cost – задаёт необходимую алгоритмическую сложность, стандартно она 10, чем выше сложность, тем дольше будет генерироваться пароль, и соответственно, тем дольше будет загружаться страница;
salt – соль для хеширования, некая уникальная строка, которая увеличивает сложность дешифровки пароля. На данный момент, используется автоматическая соль, но об этом чуть ниже;
хэш – хэш пароля.

То есть, пароль шифруется при помощи определенного алгоритма, сложности и соли.

Как применять функцию password_hash в PHP?

Функция должна содержать 2 аргумента, сам пароль и алгоритм. PASSWORD_DEFAULT, PASSWORD_BCRYPT – наиболее чаще встречаются в качестве алгоритмов, особенно PASSWORD_BCRYPT. Такой хэш пароля, в отличие от md5, при перезагрузке страницы, всегда будет уникальным, и его длина, независимо от выбранной сложности, всегда 60 символов.
Выглядит это следующим образом:

echo password_hash('test123', PASSWORD_DEFAULT); // $2y$10$kPuLknA408BkgnaKVUh8EOQOm1dRUUkufeqvG6OoIvpGDopPGea1q echo password_hash('test123', PASSWORD_BCRYPT); // $2y$10$jFmerATwXASg0WvV3W9pt.fK1UQmnnLrKao35r6/VJfzz7NPxszCq echo mb_strlen(password_hash('test123', PASSWORD_BCRYPT)); // 60

Как же нам увеличить сложность алгоритма? Для этого нужно использовать третий аргумент функции, который не обязательный, это опции:

echo password_hash('test123', PASSWORD_BCRYPT, ['salt' => 'ttttttttttttttttttttttttt']); // $2y$10$ttttttttttttttttttttteRXxHYSDzcdOi/S1JzEheCNMETevWiKC echo password_hash('test123', PASSWORD_BCRYPT, ['cost' => 12]); // $2y$12$wNh3cx81xQzXvOKCwPuerOOBOyyxgE3noJQsp3L3RYDMy43CTs4n2

Через массив мы указываем salt – и она уже будет являться частью строки. Если вы внимательно изучите сам процесс создания этого участка “из соли”, то обнаружите, что она может записаться не полностью, или может быть не достаточно сложной. В настоящее время не рекомендуется её задавать явно, а начиная с PHP 8 её просто игнорируют, и всё равно генерируют автоматически.

Внимание
Эта опция объявлена устаревшей. Рекомендуется использовать автоматически генерируемую соль. Начиная с PHP 8.0.0 явно заданная соль игнорируется.

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

/** * Данный код замерит скорость выполнения операции хеширования для вашего сервера * с разными значениями алгоритмической сложности для определения максимального * его значения, не приводящего к деградации производительности. Хорошее базовое * значение лежит в диапазоне 8-10, но если ваш сервер достаточно мощный, то можно * задать и больше. Данный скрипт ищет максимальное значение, при котором * хеширование уложится в 50 миллисекунд. */ $timeTarget = 0.05; // 50 миллисекунд. $cost = 8; do < $cost++; $start = microtime(true); password_hash("test", PASSWORD_BCRYPT, ["cost" =>$cost]); $end = microtime(true); > while (($end - $start) < $timeTarget); echo "Оптимальная стоимость: " . $cost;

Как проверить хэш пароля в PHP?

Делается это при помощи специальной функции, password_verify:

$hash = '$2y$10$ttttttttttttttttttttteRXxHYSDzcdOi/S1JzEheCNMETevWiKC'; if (password_verify('test124', $hash)) < echo 'done'; >else

Пара моментов на которые стоит обратить внимание:
1. Один и тот же пароль, зашифрованный при помощи функции password_hash, всегда будет иметь разный хеш, но при этом, password_verify – раскодирует его именно так как нужно.
2. От одной версии языка PHP к другой, с течением времени, с изменением общей ситуации в мире безопасности, да и вообще, в контексте разного “железа” на вашем сервере, нужно думать наперед, и писать код через password_needs_rehash.

Что такое password_needs_rehash?

password = 'rasmuslerdorf'; $hash = '$2y$10$YCFsG6elYca568hBi2pZ0.3LDL5wjgxct1N8w/oLR/jfHsiQwCqTS'; // Параметр стоимости может изменяться в связи со сменой оборудования $options = array('cost' => 11); // Проверка сохранённого хеша с помощью пароля if (password_verify($password, $hash)) < // Проверяем, не нужно ли использовать более новый алгоритм // или другую алгоритмическую стоимость if (password_needs_rehash($hash, PASSWORD_DEFAULT, $options)) < // Если таки да, перехешируем и сохраняем новый хеш $newHash = password_hash($password, PASSWORD_DEFAULT, $options); >// Авторизуем пользователя >

Опять же, замечательный пример из документации, который будет создавать новый хэш пароля, вам нужно будет перезаписать его в базе данных, в случае таких вот изменений обстоятельств, которые описаны в пункте 2. Изменили ‘cost’ => 13, пожалуйста, вот вам новый пароль).
Долго загружается страница, вернулись на стандартные 10, и снова всё автоматически работает, песня! 🙂 .

И всё таки, может ли владелец сайта расшифровать такой пароль? Ответ – если это md5 или base65, да, запросто, если это password_hash с автоматической солью – то удачи ему 🙂 . Такие пароли, в данный момент времени, считаются надежными.

На этом всё, надеюсь было интересно 🙂 .

Источник

Как хранить пароли в БД (PHP). Шифрование, хеширование паролей

Главная причина - минимизация ущерба в случае утечки базы данных.

Если злоумышленник получит только логины и email-адреса пользователей - это плохо, но не критично.

Но если в его руках окажутся логины и пароли, он может попытаться использовать эти данные для входа в почтовые сервисы (Gmail, Яндекс.Почта, Mail.ru и т.д.), социальные сети, мессенджеры, клиент-банки и т.д.

В тот же личный кабинет Пятёрочки, чтобы перевыпустить карту и потратить чужие бонусы.

Мем с бабкой - Где мои баллы?!

В общем, пользователи сайта, которые везде используют одни и те же логины и пароли, могут получить кучу проблем.

Некоторые разработчики считают, что их приложение надёжно защищено и никаких утечек быть не может. Есть несколько причин, почему это мнение ошибочно:

  • Разработчик - не робот, он не может не совершать ошибок.
  • Взлом может произойти со стороны хостинг-провайдера, работу которого не всегда возможно контролировать.
  • Некорректная настройка сервера может привести к возможному доступу других пользователей хостинга к вашему сайту (актуально для виртуальных хостингов).
  • Бывший коллега по работе может слить базу данных конкурентам. Может в качестве мести, а может просто ради денег.

Короче, пароли в открытом виде хранить нельзя.

Шифрование и хеширование

Шифрование - это обратимое преобразование текста в случайный набор символов.

Хеширование - это необратимое преобразование текста в случайный набор символов.

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

Приведу пример шифрования. У нас есть сообщение:

Зашифруем сообщение по следующему алгоритму: сдвинем каждую букву на 1 в алфавитном порядке, т.е. а превращается в б , г превращается в д , я превращается в а . Так будет выглядеть зашифрованный текст:

Зашифровали. Теперь для расшифровки нужно выполнить обратную операцию, сдвинуть все буквы на 1 символ назад. К слову, этот алгоритм шифрования называется шифр Цезаря (Википедия).

В отличие от шифрования, хеширование не имеет (вернее, не должно иметь) способа "расхешировать" строку обратно:

Шифрование паролей

Не надо шифровать пароли.

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

Хеширование паролей и авторизация

Для хеширования паролей в PHP существует функция password_hash() :

$password = '123456'; $hash = password_hash($password, PASSWORD_BCRYPT); var_dump($hash); // string(60) "$2y$10$Vb.pry5vRGNrm6Y79UfBsun/RbXq2.XEGCOMpozrDwg.MNpfxvWHK"

Вторым параметром передаётся алгоритм хеширования. По-умолчанию это указанный нами bcrypt, но я рекомендую указывать его вручную, поскольку базовый алгоритм в будущем может поменяться. Будет грустно, если при очередном обновлении версии PHP на сайте отвалится авторизация.

Для проверки корректности введённого пользователем пароля используется функция password_verify() :

Ещё раз. При регистрации пользователя нужно передать пароль в функцию password_hash() , а полученный хеш сохранить в базу данных.

При попытке авторизации получаем пользователя по его логину и проверяем функцией password_verify() , соответствует ли хеш пароля тому паролю, который ввёл пользователь.

Таким образом, хранить исходный пароль больше нет смысла.

Да, разные алгоритмы хеширования генерируют хеш разной длины, поэтому рекомендуется хранить хеш в поле с типом VARCHAR(255).

Алгоритмы MD5 и SHA1

В интернете ещё встречаются статьи, где рекомендуется хешировать пароли функциями md5() и sha1() .

Для хеширования паролей их использовать нельзя!

Эти алгоритмы давно устарели и не являются безопасными (Документация). Вместо этого используйте функцию password_hash() , которую мы разобрали выше.

Источник

Оцените статью