Как сделать хеширование пароля php
В предыдущей статье о функциях md5 (), sha1 () и hash () мы видели, что одним из основных недостатков метода было то, что эти алгоритмы были очень быстрыми из-за меньшей сложности и, следовательно, более уязвимы для атак, они даже Предложено не использовать в полноценном проекте большей важности. Таким образом, PHP теперь предоставляет пару новых методов для хеширования пользовательских паролей гораздо более оптимизированным и безопасным способом. Методы обсуждаются следующим образом:
функция crypt ()
Синтаксис:
Параметры : Функция может принимать максимум два параметра следующим образом:
- $ string: этот параметр ожидает хеширование строки.
- $ salt: по определению это необязательный параметр, но почти никогда не ожидается, что поле соли будет неопределенным. Параметр соли предполагает, что в качестве основы хеширования будет использоваться случайная строка. Многие разработчики склонны использовать комбинацию некоторых определенных полей и случайных символов, добавляемых вместе.
Тип возврата : эта функция возвращает хешированную строку.
Так как crypt () был лучше, чем его предшественники, он широко использовался, но надежность функции была сомнительной, поэтому PHP теперь предоставляет встроенную функцию для обслуживания хеширования паролей и рекомендуется для использования.
Функция password_hash ()
Синтаксис:
Параметры : функция может принимать до трех параметров следующим образом:
- $ string: этот параметр ожидает хеширование строки.
- $ algo: этот параметр ожидает целочисленное значение, которое относится к алгоритму, который будет использоваться для этой цели. Доступны три алгоритма:
- PASSWORD_DEFAULT: это рекомендуемый алгоритм, так как команда разработчиков PHP добавляет новые алгоритмы и обновляет следующее, чтобы быть лучшим вариантом.
- PASSWORD_BCRYPT: этот алгоритм использует алгоритм CRYPT_BLOWFISH и генерирует эквивалентный хэш crypt ().
- PASSWORD_ARGON2I: Использует алгоритм хеширования Argon2.
Поддерживаемые параметры для PASSWORD_BCRYPT :
- Стоимость: максимальная алгоритмическая стоимость, которая будет применена. Значение по умолчанию — 10. Алгоритмическая стоимость напрямую влияет на время загрузки и существенно зависит от работающего оборудования.
- Соль: Разработчики могут также предоставлять ручные соли, но это не рекомендуется.
Поддерживаемые параметры для PASSWORD_ARGON2I :
- Стоимость памяти: максимальная стоимость памяти, применяемая для генерации хэша.
- Стоимость времени: максимальное время, необходимое для вычисления хэша.
- Темы: количество потоков, которые будут использоваться.
Тип возврата : эта функция возвращает хешированную строку в случае успеха или FALSE.
Ниже программа иллюстрирует работу crypt () и password_hash () в PHP:
// PHP-код для иллюстрации работы
// crypt () и password_hash ()Хеширование - это шифрование короткой строки. В результате получается другая строка определённой длины, например 32 символа. Обычно делают хэширование паролей. Способов расшифровки хешированного пароля нет. Возможен только подбор. Поэтому хранение паролей в таком виде безопаснее, чем в обычном.
В PHP есть несколько функций для хэширования строки. Раньше самой распространённой была функция md5() . Но она работает слишком быстро и позволяет достаточно быстро подобрать пароль. Поэтому использовать её нежелательно. Наиболее удобной функцией является password_hash() с алгоритмом хеширования PASSWORD_BCRYPT . Она возвращает строку в зашифрованном виде.
password_hash (пароль, алгоритм, настройки)
пароль - пароль, который хешируется
алгоритм - алгоритм хеширования. Принимает значения: PASSWORD_DEFAULT и PASSWORD_BCRYPT.
настройки - настройки функции. Их менять не рекомендуется
Запустите скрипт и посмотрите, как выглядит хешированная строка.
Когда пользователь авторизуется на сайте и вводит пароль, его нужно сравнить с хэшированной строкой. Для этого есть функция password_verify() . Она возвращает true , если строка совпадает с паролем, зашифрованным функцией password_hash() , и false , если строка не соответствует паролю.
password_verify (пароль, хешированная строка)
пароль - пароль, введённый пользователем
хешированная строка - строка, с которой сравнивается пароль
Добавим в скрипт проверку введённого пароля:
При хешировании применяется соль. Эта информация не имеет практического значения, потому что функция password_hash() добавляет соль автоматически. Но Вы можете встретить этот термин, и нужно знать, что он означает. Соль - это набор символов, который добавляется к паролю перед хешированием. Она используется потому, что есть возможность расшифровать строку. Это делают с помощью баз данных, которые содержат огромное количество паролей и соответствующих им хешированных строк. Использование соли делает расшифровку сложнее. Расшифрованная строка не совпадает с паролем, потому что она имеет лишние символы. Авторизоваться с помощью расшифрованной строки не получится, она не соответствует паролю.
Хеширование обычно применяется в функциях регистрации и авторизации пользователей.
Всегда нужно использовать хеширование паролей. Хранение паролей в незашифрованном виде делает сайт небезопасным и позволяет злоумышленникам получить доступ к данным пользователей и совершать нежелательные действия с их аккаунтов. Это может испортить репутацию Вашему сайту.
Большинство разработчиков и CMS старого образца выполняют хеширование паролей на php, используя устаревшие алгоритмы sha256 и md5, что ставит под угрозу защищенность данных пользователей. На данный момент хранение паролей осуществляется в базе данных, а значит, при получении доступа, злоумышленник сможет, используя несложные алгоритмы, с учетом текущего технического развития, расшифровать данные старого образца в течение короткого промежутка времени.
Алгоритмы хеширования на PHP начиная с версии 5.5
С выходом PHP 5.5 работа с паролями значительно упрощается. Появился API хеширования, в состав которого входит четыре функции:
- password_hash(string $password, int $algo [, array $options(salt, cost) ]): выполняет хеширование, принимает 3 аргумента - пароль, используемый алгоритм хеширования, ассоциативный массив с опциями: salt - соль, cost - алгоритмическая стоимость вычисления пароля. Если последний аргумент отсутствует, будет создана случайная соль и использована алгоритмическая стоимость вычисления по умолчанию. Возвращает зашифрованный пароль или FALSE в случае возникновения ошибки;
- password_verify(string $password, string $hash): проверяет, соответствие пароля с заданным хэшем. Этот хэш может быть создан с помощью password_hash() или обычный crypt() хэш. Возвращает TRUE, если пароль и хэш соответствуют или в противном случае FALSE;
- password_needs_rehash(string $hash, string $algo [, string $options ]): проверяет, соответствует ли предоставленный хэш заданному алгоритму и опциям. Если нет, то считается, что хэш должен быть изменён. Принимает три аргумента - проверяемый хэш, используемый алгоритм хеширования пароля, ассоциативный массив с опциями аналогичными опциям из функции password_hash(). Возвращает TRUE, если хэш должен быть изменён, чтобы соответствовать данному алгоритму и опциям, или в противном случае FALSE;
- password_get_info(string $hash): Возвращает информацию о данном хэше. Возвращает ассоциативный массив с тремя элементами(ключами): алгоритм(algo), который будет соответствовать константе алгоритма пароля, название алгоритма(algoName), которое имеет человечески читаемое название алгоритма, ассоциативный массив с опциями (options), который включает в себя возможности, предоставляемые при вызове password_hash().
Дополнительные параметры хеширования
- PASSWORD_BCRYPT = 1: используется для создания нового хэш пароля с использованием алгоритма CRYPT_BLOWFISH;
- PASSWORD_DEFAULT = PASSWORD_BCRYPT: используется алгоритм хеширования по умолчанию, если алгоритм не задан. Он может измениться в новых версиях PHP, когда будут поддерживаться новые, более эффективные (например, Scrypt) алгоритмы хеширования.
Генерация соли для пароля
Чем выше значение параметра cost, тем выше эффективность защиты, поэтому следует увеличивать его, в зависимости от технической оснащенности используемого оборудования. Так же одним из главных преимуществ является полная автономия параметра salt (теперь он хранится в хэше), который можно генерировать автоматически и не хранить в отдельном поле.
password_hash() создает хеш пароля используя сильный, необратимый алгоритм хеширования. Функция password_hash() совместима с функцией crypt() . Следовательно, хеши паролей, созданные crypt() можно использовать с password_hash() .
В данный момент поддерживаются следующие алгоритмы:
- PASSWORD_DEFAULT - используется алгоритм bcrypt (по умолчанию с PHP 5.5.0). Обратите внимание, что используемый алгоритм может со временем меняться на более сильный, когда таковой добавляется в PHP. Соответственно и длина результата может со временем меняться. В связи с этим рекомендуется выбирать длину поля для хранения в базе данных более 60 символов (255 символов могло быть хорошим вариантом).
- PASSWORD_BCRYPT - использует алгоритм CRYPT_BLOWFISH . Генерирует стандартный хеш, совместимый с генерированным функцией crypt() с использованием идентификатора "$2y$". В результате будет сгенерирована строка длиной 60 символов, или false в случае возникновения ошибки.
- PASSWORD_ARGON2I - Использовать алгоритм хеширования Argon2i. Этот алгоритм доступен только если PHP собран с поддержкой Argon2.
- PASSWORD_ARGON2ID - Использовать алгоритм хеширования Argon2id. Этот алгоритм доступен только если PHP собран с поддержкой Argon2.
Поддерживаемые опции для PASSWORD_BCRYPT :
salt ( string ) - для самостоятельного задания соли для хеширования. Обратите внимание, что это приведет к переопределению и предотвращению автоматического создания соли.
Если не задано, то password_hash() будет генерировать случайную соль для каждого хешируемого пароля. Это предпочтительный режим работы.
Эта опция была объявлена устаревшей начиная с PHP 7.0.0. Рекомендуется использовать автоматически генерируемую соль.
cost ( int ) - задает необходимую алгоритмическую сложность. Пример использования этого значения можно посмотреть на странице посвященной функции crypt() .
Если не задано, то будет использовано значение по умолчанию 10 . Это хорошая базовая стоимость, но вы можете ее увеличить в зависимости от возможностей своего оборудования.
Поддерживаемые опции для PASSWORD_ARGON2I и PASSWORD_ARGON2ID :
memory_cost ( int ) - Максимальный размер памяти (в килобайтах), которую можно использовать для вычисления хеша Argon2. По умолчанию PASSWORD_ARGON2_DEFAULT_MEMORY_COST .
time_cost ( int ) - Максимально возможное время^ которое можно потратить для вычисления хеша Argon2. По умолчанию PASSWORD_ARGON2_DEFAULT_TIME_COST .
threads ( int ) - Количество потоков, которые можно использовать для вычисления хеша Argon2. По умолчанию PASSWORD_ARGON2_DEFAULT_THREADS .
Список параметров
Использование алгоритма PASSWORD_BCRYPT приведёт к обрезанию поля password до максимальной длины 72 символа.
Константа, обозначающая используемый алгоритм хеширования пароля.
Ассоциативный массив с опциями. За документацией по поддерживаемым опциям для каждого алгоритма обратитесь к разделу Константы алгоритмов хеширования паролей.
Если не задано, то будет использована стандартная стоимость и соль будет генерироваться автоматически.
Возвращаемые значения
Возвращает хешированный пароль или false в случае возникновения ошибки.
Использованный алгоритм, стоимость и соль будут возвращены как часть хеша. Таким образом, информация, необходимая для проверки хеша будет в него включена. Это позволит функции password_verify() проверять хеш без необходимости отдельного хранения информации о соли и алгоритме.
Список изменений
Версия Описание 7.4.0 Параметр algo сейчас ожидает строку ( string ), но все еще принимает число ( int ) для обратной совместимости. 7.3.0 Добавлена поддержка алгоритма хеширования паролей Argon2id с помощью PASSWORD_ARGON2ID . 7.2.0 Добавлена поддержка хеширующего алгоритма Argon2i с помощью PASSWORD_ARGON2I . Примеры
/**
* Мы просто хотим захешировать свой пароль используя настройки по умолчанию.
* Значит будет использован BCRYPT и результат будет 60 символов длиной.
*
* Помните, что алгоритм по умолчанию может измениться в будущем, так что
* имеет смысл заранее позаботиться о том, чтобы система хранения хешей
* смогла хранить более 60 символов (255 в самый раз)
*/
echo password_hash ( "rasmuslerdorf" , PASSWORD_DEFAULT );
?>Результатом выполнения данного примера будет что-то подобное:
/**
* Тут мы увеличиваем алгоритмическую стоимость BCRYPT до 12.
* Но это никак не скажется на длине полученного результата, она останется 60 символов
*/
$options = [
'cost' => 12 ,
];
echo password_hash ( "rasmuslerdorf" , PASSWORD_BCRYPT , $options );
?>Результатом выполнения данного примера будет что-то подобное:
$cost = 8 ;
do $cost ++;
$start = microtime ( true );
password_hash ( "test" , PASSWORD_BCRYPT , [ "cost" => $cost ]);
$end = microtime ( true );
> while (( $end - $start ) $timeTarget );echo "Оптимальная стоимость: " . $cost ;
?>Результатом выполнения данного примера будет что-то подобное:
Думаю, ни для кого ни секрет, что нельзя хранить пароли в открытом виде. В целях безопасности их необходимо хешировать. Без хеширования пароли могут быть украдены злоумышленниками с помощью найденных уязвимостей в коде приложения, и в дальнейшем могут быть использованы для компрометации аккаунтов на других сервисах.
Увы, но многие пользователи повсюду используют один и тот же пароль, чем и пользуются злоумышленники.
Применяя хеширующий алгоритм на пользовательских паролях перед сохранением их в базе данных, невозможно увидеть в открытом виде оригинальный пароль, даже в случае его кражи. В то же время, имеется возможность безопасно сравнивать оригинальный хэш пароля сохраненного в базе данных, с принятым от пользователя захешированным паролем (например, при авторизации пользователя).
Хеширование паролей защищает их только от компрометирования в вашем хранилище, но никак не защищает от внедрения вредоносного кода в ваши приложения (в случае наличия уязвимости разумеется).
Компания Google давно выразила своё недоверие SHA -1, особенно в качестве использования этой функции для подписи сертификатов TLS . Ещё в 2014 году, вскоре после публикации работы Марка Стивенса, группа разработчиков Chrome объявила о постепенном отказе от использования SHA -1. В сравнении с SHA -1 теоретическая криптостойкость ГОСТ Р 34.11-94 равна 2 128 , что во много раз превосходит 2 80 для SHA -1.
Многие профессионалы в области кибер-безопасности строго не рекомендуют использовать MD5 и SHA -1 для хеширования паролей.
Начиная с версии PHP 5.5 существует встроенное API хеширования паролей, которое позволяет безопасно не только хешировать, но и проверять пароли.
password_hash()
Итак, первая функция password_hash — создает хеш пароля, используя сильный, необратимый алгоритм хеширования. Функция password_hash() совместима с функцией crypt() . Поэтому, хеши паролей, созданные crypt() можно использовать с password_hash() .
Список параметров:
string password_hash (string $password, integer $algo [, array $options ])
$password – пользовательский пароль, строковый параметр.
$algo – константа, обозначающая используемый алгоритм хеширования пароля.
$options – ассоциативный массив с опциями salt и cost.Обратите внимание:
Параметр salt признан устаревшим, начиная с PHP 7.0.0 и настоятельно не рекомендуется к использованию.Параметр cost – задает необходимую алгоритмическую сложность (стоимость).
Если опции не заданы, то будет использована стандартная стоимость, и соль будет генерироваться автоматически.
Функция возвращает хешированный пароль, или FALSE в случае возникновения ошибки.
Пример поиска хорошего значения стоимости для password_hash() :
password_verify()
Вторая функция password_verify — проверяет, соответствует ли пароль созданному хешу.
Обратите внимание:
password_hash() возвращает алгоритм, стоимость и соль как части хеша. Таким образом, вся необходимая для проверки информация включена в него. Это позволяет производить проверку без необходимости хранить все эти данные раздельно.Список параметров:
boolean password_verify (string $password, string $hash)
$password – пользовательский пароль, строковый параметр.
$hash – строковый параметр хеш, созданный функцией password_hash() .Возвращает TRUE или FALSE , в зависимости от результатов проверки.
Заключение
Подводя итог, хотелось бы призвать всех программистов, правильно выбирать алгоритмы хеширования и проверки хешей, т.к. даже при проверке пароля нужно опасаться атак по времени, используя безопасные, на первый взгляд, инструменты сравнение строк. Ни операторы PHP == и === , ни функция strcmp() не являются таковыми. Функция password_verify() как раз делает то, что нужно.
Настоятельно рекомендую использовать встроенное API хэширования паролей, если есть такая возможность.
Читайте также: