bcrypt 加密的坑
背景
原来使用 php 开发的一个项目后端要换成 node,用户密码使用的 bcrypt 加密,数据库保存的加密后的密码,换成 node 后发现总是提醒密码错误。
测试
然后自己写了个测试发现同样的明文密码和加密后的密码,在 PHP 和 node 中校验结果居然不同!!!
PHP 版,结果正确:
$pwd = 'verygood';
$hash = '$2y$10$2H4dc/JFic6SZF7icQfpmuogmxXDjSq4OOfjr8rxWr81pfq7rnlV2';
if (password_verify($pwd, $hash)) {
echo '密码正确';
} else {
echo '密码错误';
}
node 版,结果错误:
// 引入bcrypt模块
var bcrypt = require('bcrypt')
const pwd = 'verygood'
const hash = '$2y$10$2H4dc/JFic6SZF7icQfpmuogmxXDjSq4OOfjr8rxWr81pfq7rnlV2'
const compare = bcrypt.compareSync(pwd, hash)
if (compare) {
console.log('密码正确')
} else {
console.log('密码错误')
}
然后我分别使用 PHP 和 node 加密同样的密码
PHP 加密:
$pwd = 'verygood';
$hash = password_hash($pwd, PASSWORD_BCRYPT, ['cost' => 10]);
echo $hash;
// 结果
// $hash = '$2y$10$fqEsEo0u5PJd5jVdKFJp3OWfHt4o591oH.FDTOB.sDL7/n6FKW8Tm';
PASSWORD_BCRYPT – Use the CRYPT_BLOWFISH algorithm to create the hash. This will produce a standard crypt() compatible hash using the “$2y$” identifier. The result will always be a 60 character string, or FALSE on failure.
根据函数说明我们可知 PASSWORD_BCRYPT 使用的 CRYPT_BLOWFISH 算法,CRYPT_BLOWFISH 算法盐值格式规定是 :
以$2y$开头 + 一个两位cost参数 + $ + 22位随机字符(“./0-9A-Za-z”)
node 加密:
// 引入bcrypt模块
var bcrypt = require('bcrypt')
const pwd = 'verygood'
const hash = bcrypt.hashSync(pwd, bcrypt.genSaltSync())
// 结果
// hash = '$2b$10$6FBNvMILF8RrRMP5BxfPOuNPu8mWEDppksdQjVQd7Qkaf3rzYtlbi';
This library supports $2a$ and $2b$ prefix bcrypt hashes. $2x$ and $2y$ hashes are specific to bcrypt implementation developed for Jon the Ripper. In theory, they should be compatible with $2b$ prefix.
Compatibility with hashes generated by other languages is not 100% guaranteed due to difference in character encodings. However, it should not be an issue for most cases.
node 的 bcrypt 以$2a$
和$2b$
开头,理论上,与$2y$
前缀兼容。 but 由于字符编码不同,与其他语言生成的哈希的兼容性不是 100%保证
好吧,然后我把原来使用 PHP 生成的 hash 前缀从$2y$
改成$2b$
,
登录成功
问题解决
PREV
Win10 安装和使用 Linux 的 Bash shell
NEXT