返回PHP的新密码散列API中使用的salt值

时间:2013-05-07 19:53:35

标签: php passwords salt

我目前正在实施一个利用PHP的new(将作为v5.5的一部分发布)密码处理API的webapp。我认为它真的很好,但我想知道是否有人知道为什么password_get_info()不返回给定哈希计算中使用的salt值? RFC明确指出有问题的函数不返回salt,但没有解释为什么:

  

第二个元素是“选项”,其中包括使用的选项   散列算法,但使用的盐除外。

我问的原因是因为当用户的密码到期时,我需要检查他们是否重新提交与当前密码相同的密码。执行此操作的唯一方法是对新密码进行哈希处理,使用相同的算法,成本和盐将生成的哈希值与当前数据库中的哈希值进行比较。算法和费用由password_get_info()函数返回,但不归盐。目前,我使用substr($hash, 7, 22)来获取盐值,但这显然是算法特定的,有点挫败了使用其他非常容易使用且功能强大的API的目的(如果我开始使用新算法的位置盐很可能会改变。)

编辑:我是个白痴,我不需要重建哈希并比较结果哈希,而是调用password_verify()并检查它是否返回FALSE。这会教我在生病和疲倦的情况下工作!

2 个答案:

答案 0 :(得分:2)

相反,您无需了解此信息。只需将输入与之前的哈希进行比较(通过这个,我的意思是存储用户拥有的每个哈希的记录并遍历所有哈希,检查password_verify对新密码输入的结果。)
Bcrypt很有用;实际上,这是password_hashpassword_verify将使用的任何算法的必需行为,因为否则您无法以相同的方式进行比较,并且功能会发生变化。

password_verify(string $password, string $hash):
    $hash = crypt($plaintext, '$2y$' . $workrate . '$' . $salt)
    => $2y$<workrate>$<salt><hash> as result,

但是,如果你真的需要找到bcrypt哈希的盐(这是password_hash使用的),那么只需取哈希的前22个字符,减去设置(但我会重复,但是,你只需要将输入与哈希进行比较)。

理想情况下,您应该将password_hash包装在可以处理动态工作量和更改选项的类或函数中(例如,如果将哈希值保存为工作率12,则可以使用不同的工作率基于哈希的年龄,并鼓励用户更新他们的密码。)

函数不返回salt,因为它是由CSPRNG生成的,根本不需要作为单独的参数进行比较(因为它是散列的一部分)

答案 1 :(得分:0)

这是一个老问题,但我认为我的回答高于目前接受的范围。

那么password_get_info()为什么不给你一个盐?这是因为您的salt已经存储在哈希中。因此,当你向password_verify提供hast时,它可以提取盐。

自己检查一下:

password_hash('password', PASSWORD_DEFAULT, [
   'salt'  => 'mySaltShouldBeVeryLong
]);

结果如下:"$2y$10$mySaltShouldBeVeryLonevYKGp78vooNv9Y7Kwy29CBdNLSUOutS"。如果您仔细观察,您会注意到与盐的相似性。但提供自己的盐并不是一个好主意(很难让它变得独一无二)。因此,算法将负责生成自己的盐。因此,您可以看到

password_hash('password', PASSWORD_DEFAULT) !== 
password_hash('password', PASSWORD_DEFAULT)

哈希是完全不同的,因为使用了不同的盐。这样做是因为普通开发人员的安全性不强,不知道盐,胡椒,碰撞和其他很酷的词汇是什么。

使用password_hash()创建哈希值,使用password_verify()检查是否正确。看一下password_hash()中的成本参数。