2

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

第二个元素是“选项”,它包括哈希算法使用的选项,除了使用的盐。

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

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

4

2 回答 2

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,您可以根据哈希的年龄使用不同的工作率,并鼓励用户更新他们的密码)。

这些函数不返回盐,因为它是由CSPRNG生成的,并且根本不需要作为单独的参数进行比较(因为它是哈希的一部分)

于 2013-05-07T19:59:11.290 回答
0

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

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

自己检查一下:

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() 中的一个成本参数。

于 2014-03-09T04:09:45.080 回答