Я изменил свой старый пост. Я попробовал функцию crypt () и теперь пытаюсь работать с password_hash () и password_verify (), чтобы проверить зашифрованный пароль, поступающий из базы данных, но при каждом вызове функция password_hash () перенастраивает другую зашифрованную строку и пароль_verify () не может ее сопоставить.
Вот как я это делаю.
//please ignore the syntax error if any $data = '11'; $dbpass = password_hash($data, PASSWORD_BCRYPT); echo $dbpass; // displays the random strings on each page refresh.
После того, как пароль сохранен в базе данных, не получается совпадение во время процесса входа в систему. Ниже приведена моя фактическая функция.
private function process_data($password){ $password = __STR.$password.__STR; return password_hash($password, PASSWORD_BCRYPT); } private function processed($login_password, $dbpassword){ $login_password = __STR.$login_password.__STR; return password_verify($login_password, $dbpassword); }
В каждом вызове функции для создания хешированной строки для пароля функция возвращает другую строку в следующий раз.
Хорошо. Давайте рассмотрим это один за другим.
Во-первых, это хеширование , а не шифрование . Шифрование является двусторонним, хеширование – это один из способов. Мы хотим хэш. Мы никогда не хотим шифровать. Да, терминология имеет значение. Пожалуйста, используйте правильную терминологию.
Затем каждый вызов функции password_hash
должен возвращать другой хеш. Это потому, что он создает сильную случайную соль. Вот как это было разработано и как вы действительно должны его использовать.
Кроме того, НЕ делайте «перец», добавляя __STR
до и после пароля. Вы ничего не делаете, но потенциально ослабляете пароль пользователей (что не очень хорошо). Если вам нужна дополнительная информация о том, почему это плохая идея: прочитайте этот ответ .
Продолжая, я настоятельно рекомендую вам не использовать crypt
напрямую. На самом деле удивительно легко завинчивать и генерировать чрезвычайно слабые хеши. Вот почему был разработан пароль_ password_*
api. crypt
– библиотека низкого уровня, вы хотите использовать в своем коде библиотеку высокого уровня. Для получения дополнительной информации о способах испортить bcrypt, ознакомьтесь с моим блоком: « Семь способов нарисовать Bcrypt» .
API паролей был разработан как простой, универсальный магазин. Если он не работает для вас, проверьте следующее:
Вы используете PHP> = 5.5.0? Или вы используете PHP> = 5.3.7 с password_compat ?
Является ли ваш столбец базы данных достаточно широким?
Он должен иметь длину не менее 60 символов.
Вы проверяете, что результатом функции является строка, а не bool(false)
?
Если есть внутренняя ошибка, она вернет не строку из password_hash
.
Вы получаете какие-либо ошибки?
Вы включили error_reporting
в свою максимальную настройку (я рекомендую -1
поймать все) и проверили, что код не вызывает ошибок?
Вы уверены, что используете его правильно?
function saveUser($username, $password) { $hash = password_hash($password, PASSWORD_BCRYPT); // save $username and $hash to db } function login($username, $password) { // fetch $hash from db return password_verify($password, $hash); }
Обратите внимание, что каждый из них следует вызывать только один раз.
Вы используете PHP <5.3.7 с password_compat ? Если это так, это ваша проблема. Вы используете библиотеку совместимости на неподдерживаемой версии PHP. Вы можете заставить его работать (некоторые дистрибутивы RedHat предоставили необходимые исправления), но вы используете неподдерживаемую версию. Обновите до разумного выпуска.
Если все остальное не удается, попробуйте запустить этот код и сообщить результат:
$hash = '$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG'; $test = crypt("password", $hash); $pass = $test == $hash; echo "Test for functionality of compat library: " . ($pass ? "Pass" : "Fail"); echo "\n";
Если это возвращает Fail
, вы используете неподдерживаемую версию PHP и должны обновляться. Если он возвращает пас, чем ошибка где-то в вашей логике (библиотека работает нормально).
Лучший способ хранения паролей – использовать функцию PHP password_hash () . Он автоматически генерирует криптографически безопасную соль для каждого пароля и включает ее в результирующую 60-значную строку. Вам не придется беспокоиться о соли вообще!
// Hash a new password for storing in the database. // The function automatically generates a cryptographically safe salt. $hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT); // Check if the hash of the entered login password, matches the stored hash. // The salt and the cost factor will be extracted from $existingHashFromDb. $isPasswordCorrect = password_verify($password, $existingHashFromDb);
Ваша собственная схема очень слабая, сначала вы используете MD5, который слишком быстро генерирует хэши паролей, а затем вы используете статическую соль, которая побеждает цель соли. Возможно, вы хотите взглянуть на мой учебник по безопасному хранению паролей .
Изменить ответ на обновленный вопрос:
Нет необходимости добавлять __STR
к паролю (если вы хотите добавить перец, есть лучшие способы), но ваши функции на самом деле должны работать. Возвращаемое значение password_hash()
будет отличаться каждый раз из-за случайной соли. Это правильно, функция password_verify()
может извлечь эту соль для проверки. В вашем случае поле базы данных, вероятно, является проблемой. Убедитесь, что он может содержать строку с 60 символами.