2

我正在尝试了解有关 PHP 安全最佳实践的更多信息,并且遇到了 password_hash 和 Anthony Ferrara 的password_compat项目。我想我知道如何实现它,但是在测试中,我遇到了一个奇怪的行为,这与我对密码哈希的新手理解相矛盾。

如果我将 password_hash 函数的结果保存到 MySQL 数据库用户记录中,然后使用 password_verify 检索该哈希以进行验证,它会按预期工作。但是,如果我做完全相同的事情,而不是从数据库中提取,我只是通过从数据库中复制/粘贴来硬编码密码哈希,password_verify 函数就会失败。

代码如下:

// Get the Username and password hash from the MySQL database.  GetPassTestuser routine returns an array where
//   position[0][0] is the username and position[0][1] is the password hash.
$arrUser = GetPassTestuser("mike24");
echo("User Name: ".$arrUser[0][0]."<br/>");
echo("Password hash: ".$arrUser[0][1]."<br/>");

// Run password_verify with the password hash collected from the database.  Compare it with the string "mytest"
//  (This returns true in my tests).
if (password_verify("mytest",$arrUser[0][1])){
    echo("Password verified");
} else {
    echo("Password invalid");
}
echo("<hr>Now On to our second test...<br/>");
// Now run password_verify with a string representation directly copied/pasted from the database.  This is 
//   being compared with "mytest", which in my mind should return a true value.  But it doesn't and this test
//   fails.  Not sure why.
if (password_verify("mytest","$2y$10$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm")){  // String shown here is the same as value contained in $arrUser[0][1]
    echo("2nd Test Password verified");
} else {
    echo("2nd test Password invalid");
}

虽然这不是我在真实代码中会做的事情,但我只是想了解其中的区别。为什么当我使用应该包含完全相同哈希的字符串变量时它可以正常工作,但在硬编码时它不起作用?

谢谢!

4

3 回答 3

5

来自 PHP 文档

要指定文字单引号,请使用反斜杠 () 对其进行转义。要指定文字反斜杠,请将其加倍 (\)。所有其他反斜杠实例将被视为文字反斜杠:这意味着您可能习惯的其他转义序列,例如 \r 或 \n,将按指定的字面输出而不是具有任何特殊含义。

如果遇到美元符号 ($),解析器将贪婪地获取尽可能多的标记来形成有效的变量名。将变量名括在花括号中以明确指定名称的结尾。

使用单引号

代替

"$2y$10$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm"

'$2y$10$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm'

或者

"\$2y\$10\$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm"
于 2012-10-11T16:33:25.283 回答
2

关于我的评论,我认为这会更好地作为答案:

if (password_verify("mytest",'$2y$10$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm')){  // String shown here is the same as value contained in $arrUser[0][1]
    echo("2nd Test Password verified");
} else {
    echo("2nd test Password invalid");
}
于 2012-10-11T16:34:34.453 回答
1

查看 PHP 手册中的字符串章节。简而言之,您的硬编码哈希是一个带有变量插值的 PHP 字符串:

"$2y$10$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm"
 ^  ^  ^

由于这些变量不存在,您最终会得到三个通知的空白子字符串。你应该看过通知。如果没有,请检查您的错误报告设置。

(提示:在任何地方都使用单引号,除非您确实需要变量插值。)

于 2012-10-11T16:35:30.167 回答