【问题标题】:PHP password_verify seems to work with with one string but not another that is considered equalPHP password_verify 似乎适用于一个字符串,但不适用于另一个被认为相等的字符串
【发布时间】:2014-09-25 04:11:08
【问题描述】:

我将用户名和加密密码存储在 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

【问题讨论】:

  • 用于存储哈希的列的结构是什么?
  • 另外,我不确定您是否只是因为测试而这样做,但您可以轻松地组合这两个查询。并且选择一个值时,您应该使用 @987654323 @而不是 @987654324 @之类的东西
  • 感谢迈克的提示!已经有一段时间没有做很多sql了,这很有用。哈希值存储在 VARCHAR(255) 中。
  • 嗯,那我猜这排除了哈希被截断

标签: php mysql hash passwords password-encryption


【解决方案1】:

从您的问题中不清楚变量$password 的来源,以及它是否包含与数据库中存储的文本相同的文本。

如果您进行此类测试,您必须知道函数password_hash() 将生成唯一的盐并将其包含在生成的哈希中。为了验证,您需要此盐(和其他参数)来获得可比较的哈希值。这意味着哈希每次都会不同,如果您调用 password_hash() 两次,您最终会得到不同的盐和不可比较的哈希。

我试图在另一个answer 中解释哈希格式。

[来自布鲁斯的编辑:答案见 cmets]

【讨论】:

  • 感谢您的回复!我从 $_GET 获得 $password。让我感到困惑的是,存储的未加密密码与存储的哈希和全新的哈希一起使用。我传入的密码对每个哈希都失败了。然后,当我比较存储的密码和我传入的密码时,它说它们是相等的。
  • @brucebolick - 您的 HTML 页面上是否有特殊编码,是 UTF-8 吗?你的数据库的字符集是什么?如果你不确定编码,你可以看看这个小的article。还要检查前导/尾随空格。
  • @brucebolick - 当您设置变量$password = 'yourpassword'; 硬编码时会发生什么?
  • 嗨@mar​​tinstoeckli - latin1_swedish_ci 是我数据库的排序规则。它也是字符集吗? (对不起,我真的是菜鸟。)事实证明,如果我设置 $password = 'asdf' (这是我的测试密码),它可以工作!当我设置 $password = $unencrypted 时它也有效(这不足为奇)。我认为我的 html 页面中没有特殊编码。我通过查询字符串传递密码:Request URL:localhost/project_001/oauth2-server/….
  • 我点击了发送给您的链接并仔细查看了它。我注意到我的密码前面有一个编码的空格字符“%20”。不知何故,这弄乱了哈希,但仍然通过了 strcmp 测试。我在代码中找到了将空格硬编码到查询字符串中的位置,并将其删除。这解决了我的问题。非常感谢您帮我解决问题,马丁!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-06
  • 1970-01-01
  • 1970-01-01
  • 2011-11-01
  • 1970-01-01
  • 2014-07-13
  • 1970-01-01
相关资源
最近更新 更多