PHP password_verify似乎可以处理一个字符串,但不能处理另一个被认为相等的字符串


PHP password_verify seems to work with with one string but not another that is considered equal

我将用户名和加密密码存储在mysql数据库中。仅用于测试,我还在数据库中以未加密的形式存储密码。

在下面的代码中,我从数据库中获得散列密码和未加密密码。然后我对未加密的密码进行加密。

给定的密码未通过存储的哈希或新哈希的密码验证测试。

存储的密码确实通过了存储哈希和新哈希的密码验证测试。

对strcmp的调用表示存储的密码和给定的密码相等。

这怎么可能呢?

[edit]:我正在从网页上的用户输入中传入$password。

// 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()将生成一个唯一的salt,并将其包含在生成的哈希中。为了进行验证,您需要这个salt(和其他参数)来获得可比较的哈希值。这意味着每次散列都会不同,如果你调用password_hash()两次,你最终会得到不同的盐和不可比较的散列。

我试图在另一个答案中解释散列格式。

[来自Bruce的编辑:请参阅评论以获得答案]