Использование функции PHP 5.5 password_hash и password_verify
Скажем, я хотел сохранить пароль для пользователя, будет ли это правильным способом сделать это с помощью функции PHP 5.5 password_hash()
(или этой версии для PHP 5.3.7+: https://github.com/ircmaxell/password_compat)?
$options = array("cost" => 10, "salt" => uniqid());
$hash = password_hash($password, PASSWORD_BCRYPT, $options);
Тогда я бы сделал:
mysql_query("INSERT INTO users(username,password, salt) VALUES($username, $hash, " . $options['salt']);
Вставить в базу данных.
Тогда для проверки:
$row = mysql_fetch_assoc(mysql_query("SELECT salt FROM users WHERE id=$userid"));
$salt = $row["salt"];
$hash = password_hash($password, PASSWORD_BCRYPT, array("cost" => 10, "salt" => $salt));
if (password_verify($password, $hash) {
// Verified
}
Ответы
Ответ 1
Игнорируя проблемы с вашими заявлениями о базе данных, я отвечу на вопрос о password_hash
.
Короче говоря, нет, это не так, как вы это делаете. Вы не хотите хранить соль самостоятельно, вы должны хранить как хэш, так и соль, а затем использовать оба для проверки пароля. password_hash
возвращает строку, содержащую оба.
Функция password_hash
возвращает строку, содержащую как хэш, так и соль. Итак:
$hashAndSalt = password_hash($password, PASSWORD_BCRYPT);
// Insert $hashAndSalt into database against user
Тогда для проверки:
// Fetch hash+salt from database, place in $hashAndSalt variable
// and then to verify $password:
if (password_verify($password, $hashAndSalt)) {
// Verified
}
Кроме того, как следует из комментариев, если вы заинтересованы в безопасности, вы можете посмотреть mysqli
(ext/mysql
устарел в PHP5.5), а также эту статью о SQL-инъекции: http://php.net/manual/en/security.database.sql-injection.php
Ответ 2
Использование вашей соли не рекомендуется, а с PHP 7 его использование устарело. Чтобы понять, почему, читайте мысли автора
Одна вещь стала для меня совершенно понятной: солевой вариант опасно. Я еще не видел единственного использования опции соли, которая были даже достойными. Каждое использование варьируется от плохого (прохождение mt_rand() вывода) на опасные (статические строки) до безумного (передача пароля как его собственная соль).
Я пришел к выводу, что я не думаю, что мы должны разрешать пользователям для указания соли.
Ответ 3
Обратите внимание на это из php.net
Внимание
Опция salt устарела с PHP 7.0.0. Сейчас предпочитает просто использовать соль, которая генерируется по умолчанию.
Вывод? Забудьте о солевом варианте.
Этого было бы достаточно password_hash('password', PASSWORD_DEFAULT)
* (или _BCRYPT)
Ответ 4
Вы не должны вводить собственную соль, оставлять соль пустой, функция будет генерировать хорошую случайную соль.
Вставьте в базу данных (или файл или все, что вы используете) всю строку, возвращаемую функцией. это содержит:
идентификатор алгоритма, стоимость, соль (22 символа) и пароль хэша.
Для использования функции password_verify() требуется вся строка. Соль случайна и не вредит попадать в чужие руки (с хэшированным паролем). Это предотвращает (или очень сложно) использование готовых наборов генерируемых списков паролей и хэшей - радужных таблиц.
Вам следует рассмотреть возможность добавления параметра стоимости. По умолчанию (если опущено) - 10 - если выше, то функция вычисляет хэш дольше. Увеличение стоимости на 1, удвоенное время, необходимое для генерации хэша (и, следовательно, удлинение времени, необходимого для нарушения пароля)
$hash = password_hash($password, PASSWORD_BCRYPT, array("cost" => 10));
вы должны установить этот параметр на основе проверки скорости на вашем сервере. Рекомендуется, чтобы функция выполняла 100 мс + (некоторые предпочитают делать 250 мс). Обычно стоимость = 10 или 11 является хорошим выбором (в 2015 году).
Чтобы повысить безопасность, вы можете добавить в пароли длинную (50-60 символов - хороший выбор) секретную строку. прежде чем вы будете использовать password_hash() или password_verify().
$secret_string = '[email protected]#[email protected]#$234';
$password = trim($_POST['user_password']) . $secret_string;
// here use password_* function
Внимание Использование параметра PASSWORD_BCRYPT для параметра algo приведет к усечению параметра пароля до максимальной длины 72 символа.
Если пароль $будет длиннее 72 символов, и вы измените или добавите 73 или 90 символов, хэш не изменится. Необязательно, приклеивание $secret_string должно быть в конце (после пароля пользователя, а не раньше).