- PVSM.RU - https://www.pvsm.ru -

Безопасное хранение паролей для сайтов на PHP + MySQL

По сей день очень многие [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/