Почему нельзя хранить пароли в открытом виде
Главная причина - минимизация ущерба в случае утечки базы данных.
Если злоумышленник получит только логины и email-адреса пользователей - это плохо, но не критично.
Но если в его руках окажутся логины и пароли, он может попытаться использовать эти данные для входа в почтовые сервисы (Gmail, Яндекс.Почта, Mail.ru и т.д.), социальные сети, мессенджеры, клиент-банки и т.д.
В тот же личный кабинет Пятёрочки, чтобы перевыпустить карту и потратить чужие бонусы.
В общем, пользователи сайта, которые везде используют одни и те же логины и пароли, могут получить кучу проблем.
Некоторые разработчики считают, что их приложение надёжно защищено и никаких утечек быть не может. Есть несколько причин, почему это мнение ошибочно:
- Разработчик - не робот, он не может не совершать ошибок.
- Взлом может произойти со стороны хостинг-провайдера.
- Некорректная настройка сервера может привести к возможному доступу других пользователей хостинга к вашему сайту (актуально для виртуальных хостингов).
- Бывший коллега по работе может слить базу данных конкурентам. Может в качестве мести, а может просто ради денег.
Короче, пароли в открытом виде хранить нельзя.
Шифрование и хеширование
Шифрование - это обратимое преобразование текста в случайный набор символов.
Хеширование - это необратимое преобразование текста в случайный набор символов.
Разница между этими двумя действиями в том, можем ли мы из случайного набора символов получить исходную строку по какому-то известному алгоритму.
Приведу пример шифрования. У нас есть сообщение:
Я Вася
Зашифруем сообщение по следующему алгоритму: сдвинем каждую букву на 1 в алфавитном порядке, т.е. а превращается в б, г превращается в д, я превращается в а. Так будет выглядеть зашифрованный текст:
А Гбта
Зашифровали. Теперь для расшифровки нужно выполнить обратную операцию, сдвинуть все буквы на 1 символ назад. К слову, этот алгоритм шифрования называется шифр Цезаря (Википедия).
В отличие от шифрования, хеширование не имеет (вернее, не должно иметь) способа "расхешировать" строку обратно:
$hash = md5('Какая-то строка');
Шифрование паролей
Не надо шифровать пароли.
Алгоритм дешифровки можно украсть или подобрать. При использовании хеширования неважно, знает ли его алгоритм злоумышленник, это не особо поможет ему в получении исходного пароля из хеша.
Хеширование паролей и авторизация
Для хеширования паролей в PHP существует функция password_hash():
$password = '123456';
$hash = password_hash($password);
var_dump($hash);
// string(60) "$2y$10$Vb.pry5vRGNrm6Y79UfBsun/RbXq2.XEGCOMpozrDwg.MNpfxvWHK"
Для проверки корректности введённого пользователем пароля используется функция password_verify():
<?php
$hash = '$2y$10$Vb.pry5vRGNrm6Y79UfBsun/RbXq2.XEGCOMpozrDwg.MNpfxvWHK';
$password = '123456';
if(password_verify($password, $hash))
echo 'Пароль правильный.';
else
echo 'Пароль неправильный.';
Ещё раз. При регистрации пользователя нужно передать пароль в функцию password_hash(), а полученный хеш сохранить в базу данных.
При попытке авторизации получаем пользователя по его логину и проверяем функцией password_verify(), соответствует ли хеш пароля тому паролю, который ввёл пользователь.
Таким образом, хранить исходный пароль больше нет смысла.
Да, разные алгоритмы хеширования генерируют хеш разной длины, поэтому рекомендуется хранить хеш в поле с типом VARCHAR(255).
Алгоритмы MD5 и SHA1
В интернете ещё встречаются статьи, где рекомендуется хешировать пароли функциями md5() и sha1().
Для хеширования паролей их использовать нельзя!
Эти алгоритмы давно устарели и не являются безопасными (Документация). Вместо этого используйте функцию password_hash(), которую мы разобрали выше.