Я храню имя пользователя и зашифрованный пароль в базе данных MySQL. Только для тестирования, я также храню пароль в незашифрованном виде в базе данных.
В следующем коде я получаю хешированный пароль и незашифрованный пароль из базы данных. Затем я зашифровал незашифрованный пароль.
Данный пароль не проходит проверку пароля для сохраненного хэша или нового хэша.
Сохраненный пароль проходит тест проверки пароля как для сохраненного хеша, так и для нового хеша.
Вызов strcmp говорит о том, что сохраненный пароль и данный пароль равны.
Как это могло произойти?
[править]: Я передаю $ пароль от пользовательского ввода на веб-странице.// get hashed password from database
$sql = "SELECT member_password FROM member WHERE member_username=:username;";
$stmt = $db->prepare($sql);
$stmt->bindParam("username", $username);
$stmt->execute();
$hash = $stmt->fetch(PDO::FETCH_ASSOC);
$hash = $hash["member_password"];
// get unencrypated password from database
$sql = "SELECT member_unencrypted FROM member WHERE member_username=:username;";
$db = getConnection();
$stmt = $db->prepare($sql);
$stmt->bindParam("username", $username);
$stmt->execute();
$unencrypted = $stmt->fetch(PDO::FETCH_ASSOC);
$unencrypted = $unencrypted["member_unencrypted"];
// encrypt the unencrypted password that was retrieved from the database
$encrypted = password_hash($unencrypted, PASSWORD_DEFAULT);
// given password does not pass the new hash per this test
if(password_verify($password, $encrypted))
echo '<br>given password passed new hash';
else
echo '<br>given password did not pass new hash';
// stored password does pass the new hash per this test
if(password_verify($unencrypted, $encrypted))
echo '<br>stored password passed new hash';
else
echo '<br>stored password did not pass new hash';
// given password does not pass the stored hash per this test.
if(password_verify($password, $hash)){
echo '<br>given password passed stored hash';
else
echo '<br>given password did not pass stored hash';
// stored password does pass the stored hash per this test.
if(password_verify($unencrypted, $hash))
echo '<br>stored password passed stored hash';
else
echo '<br>stored password did not pass stored hash';
// stored and given passwords are equal per this test.
if(strcmp($unencrypted, $password))
echo '<br>stored and given passwords are equal';
else
echo '<br>stored and given passwords are not equal';
Выход:
given password did not pass new hash
stored password passed new hash
given password did not pass stored hash
stored password passed stored hash
stored and given passwords are equal
Из вашего вопроса не понятно, где переменная $password
исходит из, и если он содержит тот же текст, который хранится в базе данных.
Если вы делаете такие тесты, вы должны знать, что функция password_hash()
сгенерирует уникальную соль и включит ее в полученный хеш. Для проверки вам нужна эта соль (и другие параметры), чтобы получить сопоставимое хеш-значение. Это означает, что хэш будет отличаться каждый раз, и если вы позвоните password_hash()
дважды вы получите разные соли и несопоставимые хэши.
Я пытался объяснить формат хэша в другом ответ.
[редактировать от Брюса: см. комментарии для ответа]Других решений пока нет …