私が取り組んでいるアプリの場合、nodejsはPHPによって作成されたハッシュを検証する必要があり、その逆も同様です。
問題は、PHPで生成されたハッシュ(PHPのpassword_hash
関数を使用するLaravelの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 failed nodejs pass'、一方、次の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でテストを実行しました。
Phpとnodeから生成されるbcryptハッシュのタイプが異なるため、これは失敗します。 Laravelは$2y$
を生成しますが、ノードは$2a$
を生成します。ただし、2a
と2y
の違いは接頭辞のみです。
したがって、できることは、プレフィックスの1つを他のプレフィックスと同様にすることです。お気に入り:
$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$
に変更します。
私は前に言われたことを計算して、機能するコードを取得しようとしました。ご覧のとおり、何も交換する必要はありません。
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
異なる言語での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のハッシュされた文字列をGoで比較するとエラーが発生する場合があります。