将bcrypt密码哈希从PHP迁移到Python-ValueError:哈希密码无效

将bcrypt密码哈希从PHP迁移到Python-ValueError:哈希密码无效,php,python,hash,passwords,bcrypt,Php,Python,Hash,Passwords,Bcrypt,我有一个PHP7应用程序,可以像这样散列用户密码 $hash = password_hash($password, PASSWORD_BCRYPT); 例如,如果我将test1234传递给它,我得到: $2y$10$aazE9OUKZlOQiM6axwxU/utpOURLQ58pluqtFZkkGE3R9ShtUxBOm Traceback (most recent call last): File "<stdin>", line 1, in <module>

我有一个PHP7应用程序,可以像这样散列用户密码

$hash = password_hash($password, PASSWORD_BCRYPT);
例如,如果我将test1234传递给它,我得到:

$2y$10$aazE9OUKZlOQiM6axwxU/utpOURLQ58pluqtFZkkGE3R9ShtUxBOm
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
ValueError: Invalid hashed_password salt
现在,我有了一个Python应用程序,它也必须更新用户密码。它使用的是这样的东西:

import bcrypt

hash = bcrypt.hashpw(password, bcrypt.gensalt())
$result = password_verify($password, $hash);
例如,相同的密码test1234散列如下:

$2a$12$vsI9Vf9gWj/Au3McYradxuozyZychmlfqoCJcSacDWuMzUDVpv33m
正如您所看到的,PHP生成了$2y,而Python生成了$2a,所以它们是有点不同的哈希版本

现在,如果我尝试在PHP中验证Python和PHP哈希,如下所示:

import bcrypt

hash = bcrypt.hashpw(password, bcrypt.gensalt())
$result = password_verify($password, $hash);
在这两种情况下我都是正确的。但是,如果我尝试在Python方面验证这两个方面:

bcrypt.checkpw(password, hash)
它只适用于我传递Python中生成的哈希时。如果我通过PHP生成的哈希,我得到:

$2y$10$aazE9OUKZlOQiM6axwxU/utpOURLQ58pluqtFZkkGE3R9ShtUxBOm
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
ValueError: Invalid hashed_password salt
2y和2a是。正如维基百科所说,2y只针对PHP:

2011年6月,在BCrypt的PHP实现crypt_blowfish中发现了一个bug。[...] 他们还建议让crypt_河豚为固定算法生成的散列生成$2y$

其他人,包括canonical OpenBSD,都没有采用2x/2y的概念。此版本标记更改仅限于crypt_河豚

py bcrypt模块在这里落后于时代,因为它只支持2a版本!截至2014年2月,2b版是最新版本,修复了一个对密码进行哈希处理超过255个字符的错误。目前的0.4版本是在2013发布的,所以我认为这个项目已经死了。

相反,您应该安装。虽然它只支持2a和2b来生成散列,但它是显式的,因此我使用该项目验证2y散列没有问题:

>>> import bcrypt
>>> bcrypt.__version__
'3.1.4'
>>> hash = b'$2y$10$aazE9OUKZlOQiM6axwxU/utpOURLQ58pluqtFZkkGE3R9ShtUxBOm'
>>> bcrypt.checkpw(b'test1234', b'$2y$10$aazE9OUKZlOQiM6axwxU/utpOURLQ58pluqtFZkkGE3R9ShtUxBOm')
True