2012-10-11 57 views
2

我想了解更多关于PHP安全最佳实践,和我遇到password_hash和password_compat项目由安东尼·费拉拉来了。我想我理解如何实现它,但在测试中,我遇到了一个奇怪的行为,与我对密码哈希的新手理解相矛盾。试图了解PHP password_hash

如果我救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"); 
} 

虽然这不是我在实际的代码做什么,我只是想了解有什么区别。为什么当我使用假定包含完全相同散列的字符串变量时它工作正常,但在硬编码时不起作用?

谢谢!

+3

你硬编码之一,在双引号,有美元符号解释为变量。将其更改为单引号,它可能会工作 – Jason

+0

美元符号LOL – jondinham

+0

'$ S33h20qxHndErOoxJL'被视为双引号字符串中的变量。 –

回答

5

从PHP DOC

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

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

使用单引号

更换

"$2y$10$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm" 

随着

'$2y$10$S33h20qxHndErOoxJL.sceQtBQXtSWrHieBtFv59jwVwJuGeWwKgm' 

或者

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

关于我的C omment,我想这会工作作为一个更好的答案:

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"); 
} 
+0

是的,就是这样 - 只是不得不摆脱美元符号(或使用单引号)。我希望有一个更科学的推理!谢谢! – user1720817

1

看一看PHP手册的Strings章。总之,你硬编码的哈希值是一个PHP字符串具有可变插值:

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

由于这些变量不存在,你会用空白子三个通告结束。你应该看到通知。如果您没有,请检查您的错误报告设置。

(提示:在任何地方使用单引号除非你想变插值)。