- PVSM.RU - https://www.pvsm.ru -
По сей день очень многие [1] хранят пароли в базе просто захешировав их с помощью md5 или в лучшем случае SHA-1, что едва ли обеспечивает сколь либо заметную безопасность. У устаревшего и уже признанного ненадёжным md5 существует немало коллизий, а также к нему рассчитаны довольно большие и общедоступные [2] радужные таблицы. Ситуация с SHA-1 лишь немногим лучше.
Использование соли и более стойких алгоритмов хеширование значительно увеличивают надёжность, однако рассчёт даже длинных хешей — не очень сложная задача для современных систем, особенно с тех пор как для рассчётов стали привлекать GPU. Поэтому для увеличения надёжности шифрования паролей следует использовать такой алгоритм, который будет работать настолько медленно, что рассчёт радужных таблиц и атаки методом перебора станут абсолютно неэффективными. Это делает небезызвестная функция bcrypt. Для необратимого шифрования она использует алгоритм blowfish с множеством итераций, и работает очень медленно. Путём изменения количества итераций можно регулировать время, затрачиваемое на шифрования пароля, и найти такую «золотую середину», когда шифрование одного пароля будет достаточно быстрым, а подбор его станет бессмысленным.
В PHP есть встроенная функция crypt(), являющаяся реализацией bcrypt. С версиях PHP 5.3 и выше функция crypt() имеет встроенную реализацию алгоритмов шифрования и больше не зависит от поддержки этих алгоритмов операционной системой, чем и следует воспользоваться. Эта функция поддерживает различные алгоритмы, от DES до SHA-512, и выбирает алгоритм в зависимости от того, какая соль задаётся в качестве её параметра.
Ниже я хочу предложить простейший, состоящий из одной строчки генератор соли. Будучи скормленной функции crypt() данная соль заставит её использовать blowfish с 10 в квадрате итерациями. Это задаётся идентификатором $2a$ (использовать bcrypt), и идущим затем количеством итераций, которые задаются как логарифм по основанию 2 (в данном случае это 210, то есть 1024 итераций. Увеличение параметра на единицу удваивает количество итераций, и следовательно время рассчёта функции.
// Генерируем соль
$salt = '$2a$10$'.substr(str_replace('+', '.', base64_encode(pack('N4', mt_rand(), mt_rand(), mt_rand(),mt_rand()))), 0, 22) . '$';
// Шифруем пароль с применением данной соли
$hashed_password = crypt($password, $salt);
Соль будет длиной 30 байт, из которых 22 полезных и 8 служебных. На моём сервере (Xeon E5520, 2.24 ГГц) рассчёт одного пароля таким способом занимает 0.12 секунд — что очень много. На выходе будет получена строка длиной 60 байт.
Генератор позаимствован из комментариев на странице описания функции [3] на php.net.
Автор: varnav
Источник [4]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/php-2/20328
Ссылки в тексте:
[1] очень многие: http://mashable.com/2012/06/06/6-5-million-linkedin-passwords/
[2] большие и общедоступные: http://www.freerainbowtables.com/
[3] странице описания функции: http://php.net/manual/en/function.crypt.php
[4] Источник: http://habrahabr.ru/post/159043/
Нажмите здесь для печати.