升级 PHP (<5.3.2) 使用无效 CRYPT_STD_DES salt 生成的密码

Upgrading PHP (<5.3.2) passwords generated using invalid CRYPT_STD_DES salt

长话短说,我有一些密码在 PHP 版本中被不正确地加盐和散列,如果盐无效。

但是在 PHP 5.3.2+ 中:

5.3.2 Fixed Blowfish behaviour on invalid rounds to return "failure" string ("*0" or "*1"), instead of falling back to DES.

造成这个问题的原因是盐中包含“$”字符,因为它本来是河豚盐(但在不知不觉中变形了)。

因此我无法手动执行如下操作: crypt($pass, "$a"); 因为那现在也不是有效的 CRYPT_STD_DES 盐。盐必须在“./0-9A-Za-z”范围内。它只是 returns“*0”,正如 PHP 开发者的意图。

如何在较新版本的 PHP(理想情况下至少为 7.1)中验证这些格式错误的密码?

您可能正在寻找

password_hash ( string $password , int $algo [, array $options ] ) : string

https://www.php.net/manual/en/function.password-hash.php

作为一种变通方法,我最终实际上将旧版本的 PHP 用于单个目录,在该目录中我可以进行 file_get_contents() 调用并使用旧的(错误的)算法检索哈希,但在其他地方仍然使用更现代的 PHP 版本。

然而,这不是一个合适的解决方案,因为它在技术上没有回答问题: "How can I validate these malformed passwords in a more recent version of PHP?"

因此,除非似乎没有其他可能的解决方案,否则我不会将此标记为已接受的答案(但我认为为了完整性起见应该添加此答案)。

找到实际解决方案。通过暴力破解盐,事实证明 PHP 将无效的“$2”STD_DES 盐解释为“q2”。

因此,这个问题的答案是 可以通过更改用于比较哈希值的 salt 使其以“q2”开头,从而在较新版本的 PHP 中验证这些哈希值" 而不是 "$2"。 从那里开始,可以在执行相等性检查时调用 substr_replace($str, '$', 0, 1); 将新添加的 "q" 字符替换回 "$" 字符。

作为一个轶事,显然我得到的信息是不正确的并且哈希是在 PHP 5.3.29 中生成的,这与文档所说的回落到 STD_DES 相矛盾正在 5.3.2 版本中修补。