对于我正在处理的应用程序,nodejs需要验证PHP创建的哈希值,反之亦然。
问题是,PHP中生成的哈希(通过Laravel的Hash
类,只使用PHP的password_hash
函数)在node.js中测试时返回false。
以下node.js脚本:
var bcrypt = require('bcrypt');
var password = 'password';
var phpGeneratedHash = '$2y$10$jOTwkwLVn6OeA/843CyIHu67ib4RixMa/N/pTJVhOjTddvrG8ge5.';
var nodeGeneratedHash = '$2a$10$ZiBH5JtTDtXqDajO6f4EbeBIXGwtcGg2MGwr90xTH9ki34SV6rZhO';
console.log(
bcrypt.compareSync(password, phpGeneratedHash) ? 'PHP passed' : 'PHP failed',
bcrypt.compareSync(password, nodeGeneratedHash) ? 'nodejs passed' : 'nodejs failed'
);
输出:'PHP失败的nodejs已通过',而以下PHP脚本:
<?php
$password = 'password';
$phpGeneratedHash = '$2y$10$jOTwkwLVn6OeA/843CyIHu67ib4RixMa/N/pTJVhOjTddvrG8ge5.';
$nodeGeneratedHash = '$2a$10$ZiBH5JtTDtXqDajO6f4EbeBIXGwtcGg2MGwr90xTH9ki34SV6rZhO';
print password_verify($password, $phpGeneratedHash) ? 'PHP passed' : 'PHP failed';
print password_verify($password, $nodeGeneratedHash) ? 'nodejs passed' : 'nodejs failed';
输出'PHP传递的nodejs传递'。
我使用PHP 5.5.18,node.js v0.10.32和npm bcrypt模块在Ubuntu 14.04.1中运行测试。
答案 0 :(得分:54)
这是失败的,因为从php和节点生成的bcrypt哈希的类型是不同的。 Laravel生成$2y$
,而节点生成$2a$
。但好消息是2a
和2y
之间的唯一区别是它们的前缀。
所以你可以做的是使其中一个前缀类似于另一个。像:
$phpGeneratedHash = '$2y$10$jOTwkwLVn6OeA/843CyIHu67ib4RixMa/N/pTJVhOjTddvrG8ge5.';
$nodeGeneratedHash = '$2a$10$ZiBH5JtTDtXqDajO6f4EbeBIXGwtcGg2MGwr90xTH9ki34SV6rZhO';
类似于:
$phpGeneratedHash = '$2y$10$jOTwkwLVn6OeA/843CyIHu67ib4RixMa/N/pTJVhOjTddvrG8ge5.';
$nodeGeneratedHash = '$2y$10$ZiBH5JtTDtXqDajO6f4EbeBIXGwtcGg2MGwr90xTH9ki34SV6rZhO';
请注意,我已将节点哈希的$2a$
替换为$2y$
。您只需执行以下操作:
$finalNodeGeneratedHash = str_replace("$2a$", "$2y$", $nodeGeneratedHash);
finalNodeGeneratedHash = nodeGeneratedHash.replace('$2a$', '$2y$');
然后将phpGeneratedHash
与finalNodeGeneratedHash
进行比较。
注意:如果您在PHP中进行比较,建议您将NodeJS生成的哈希的前缀更改为
$2y$
,如果您在NodeJS中进行比较,则;将PHP生成的哈希的前缀更改为$2a$
。
答案 1 :(得分:2)
我试图计算之前所说的内容,以获得有效的代码。如你所见,我不需要更换任何东西。
在PHP 7.2.4方面:
<?php
$password = "test123";
$hash = password_hash($password, PASSWORD_BCRYPT);
echo $hash; // I get $2y$10$5EaF4lMSCFWe7YqqxyBnR.QmDu1XhoiaQxrOFw.AJZkGCYmpsWDU6
在nodeJS方面:
安装bcryptjs包:npm i bcryptjs
var bcrypt = require('bcryptjs');
let hash1="$2y$10$5EaF4lMSCFWe7YqqxyBnR.QmDu1XhoiaQxrOFw.AJZkGCYmpsWDU6";
console.log(bcrypt.compareSync("test123", hash1)); // display true
答案 2 :(得分:0)
使用不同语言的bcrypt的实现可能有所不同。
例如,在Node.js版本bcrypt.js中,应用的盐长度为29个字符
bcrypt.getSalt = function(hash) {
if (typeof hash !== 'string')
throw Error("Illegal arguments: "+(typeof hash));
if (hash.length !== 60)
throw Error("Illegal hash length: "+hash.length+" != 60");
return hash.substring(0, 29);
};
但是,在Go版本golang.org/x/crypto/bcrypt中,盐大小为22个字节:
const (
majorVersion = '2'
minorVersion = 'a'
maxSaltSize = 16
maxCryptedHashSize = 23
encodedSaltSize = 22
encodedHashSize = 31
minHashSize = 59
)
因此,在Go语言中与其他语言进行比较时,Node.js中的哈希字符串可能会出错。