php crypt()河豚盐长度向后兼容

时间:2014-07-17 09:39:04

标签: php salt blowfish

我用crypt()来哈希密码,用这样的河豚盐:

  

$ 2a $,2位数,$,[a-zA-Z0-9]中的21个字符

这里我犯了一个错误,即在第三个$为21而不是22之后的字符长度。但它工作正常,所以我没有找到错误。

它适用于运行Windows和php 5.4.4的桌面以及使用php 5.3.x运行Amazon linux的AWS ec2,这个版本太短了。

有一天,我将AWS php更新为5.5.14。然后问题发生了。 crypt()一直返回*。

经过一番尝试,我在盐的末尾加了一个$,所以它变成22个字符。它再次工作并返回与以前相同的哈希字符串。虽然它不遵守河豚规则,但字符应为[./a-zA-Z0-9]

但是现在我将这个站点复制到另一台运行openSuSE 13.1和php 5.5.14的机器上,这个盐再次失败。

我将php降级到5.4.20,但没有帮助。

新网站仍然需要旧数据库,所以我必须使密码哈希工作。

影响此河豚盐长度错误兼容性问题的库或模块是什么? Tt似乎不是PHP的版本。 AWS 5.5.14

或者是否有另一个神奇的角色可以再次救我?我尝试在[./a-zA-Z0-9]中替换每个尾巴$但不幸运,哈希字符串不同....

2 个答案:

答案 0 :(得分:2)

首先,我强烈建议您使用新功能password_hash()password_verify()生成并验证新哈希值。当然,这并不能解决旧哈希的实际问题,但将它们标记为旧的可能是个好主意,因此可以在用户下次登录时更新它们。

对于这个旧的哈希,我会尝试验证它们,生成一个有效的最后一个字符22的salt。crypt函数实际上只使用字符22的部分位(盐的126位而不是128位)。因此,最后一个字符22的组将以相同的哈希值结束。

查看此问题的答案Why does crypt/blowfish generate the same hash...

如果您尝试将所有相关字符[.Oeu]作为字符22,那么一个组合产生与无效盐相同的结果的可能性很大。

编辑:

由于使用的盐成为密码哈希的一部分,您应该能够看到用作字符22的内容(第三个$之后的第22个字符)。

答案 1 :(得分:1)

使用(再次)' $'因为最后一个字符应该使你的密码工作如果你降级到PHP 5.4。

然而,这不是一个长期的解决方案。使用' $'因为最后一个字符使你的所有密码都向前兼容,因为它不是有效的Base64字符(无论是普通的还是与bcrypt兼容的Base64)。

只要您可以使用PHP 5.4,这意味着只要PHP 5.4得到官方支持,您就应该在使用它们时重新哈希所有旧密码。 删除PHP 5.4支持后,您将别无选择,只能为仍旧使用旧哈希方案的用户生成新的随机密码,并通过电子邮件发送给他们。

我还必须建议您使用password-compat package来更新密码。它将为您提供仅在PHP 5.5+上可用的password_*()函数。该软件包的作者与使用PHP本身实现这些功能的人是同一个人,因此您可以确保它既安全又100%兼容,在升级到5.5 +时为您提供向前兼容性。