Porównywanie hasha BCrypt pomiędzy PHP i NodeJS
Dla aplikacji, nad którą pracuję, nodejs musi zweryfikować hasze utworzone przez PHP i vice-versa.
Problem polega na tym, że hasze wygenerowane w PHP (przez klasę Hash
Laravela, która po prostu używa funkcji password_hash
PHP) zwracają false podczas testowania w node.js.
Następujący węzeł.skrypt 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'
);
Outputs: 'PHP failed NodeJS passed', natomiast następujący skrypt 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';
Wypisuje 'PHP przeszedł nodejs przeszedł'.
Przeprowadziłem testy w Ubuntu 14.04.1 using PHP 5.5.18, node.js v0. 10. 32 oraz moduł npm bcrypt.
3 answers
To się nie powiedzie, ponieważ typy hashów bcrypt generowanych z PHP i node są różne. Laravel generuje $2y$
, podczas gdy node generuje $2a$
. Ale dobrą wiadomością jest to, że jedyną różnicą między 2a
i 2y
są ich przedrostki.
Więc możesz zrobić jeden z prefiksów podobny do drugiego. Like:
$phpGeneratedHash = '$2y$10$jOTwkwLVn6OeA/843CyIHu67ib4RixMa/N/pTJVhOjTddvrG8ge5.';
$nodeGeneratedHash = '$2a$10$ZiBH5JtTDtXqDajO6f4EbeBIXGwtcGg2MGwr90xTH9ki34SV6rZhO';
Do czegoś takiego:
$phpGeneratedHash = '$2y$10$jOTwkwLVn6OeA/843CyIHu67ib4RixMa/N/pTJVhOjTddvrG8ge5.';
$nodeGeneratedHash = '$2y$10$ZiBH5JtTDtXqDajO6f4EbeBIXGwtcGg2MGwr90xTH9ki34SV6rZhO';
Zauważ, że zamieniłem $2a$
węzła hash na $2y$
. Możesz to po prostu zrobić z:
PHP
$finalNodeGeneratedHash = str_replace("$2a$", "$2y$", $nodeGeneratedHash);
Węzeł
finalNodeGeneratedHash = nodeGeneratedHash.replace('$2a$', '$2y$');
Następnie porównaj phpGeneratedHash
z finalNodeGeneratedHash
.
Uwaga: zaleca się, aby w przypadku porównywania w PHP zmienić prefiks wygenerowanego przez NodeJS hasha na
$2y$
, a w przypadku porównywania w NodeJS; zmienić prefiks wygenerowanego przez PHP hasha na$2a$
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-09 07:07:25
Próbowałem obliczyć to, co zostało powiedziane wcześniej, aby uzyskać kody, które działają. Jak widzisz, niczego nie muszę wymieniać.
Po stronie PHP 7.2.4:
<?php
$password = "test123";
$hash = password_hash($password, PASSWORD_BCRYPT);
echo $hash; // I get $2y$10$5EaF4lMSCFWe7YqqxyBnR.QmDu1XhoiaQxrOFw.AJZkGCYmpsWDU6
Po stronie nodeJS:
Zainstaluj pakiet bcryptjs: npm i bcryptjs
var bcrypt = require('bcryptjs');
let hash1="$2y$10$5EaF4lMSCFWe7YqqxyBnR.QmDu1XhoiaQxrOFw.AJZkGCYmpsWDU6";
console.log(bcrypt.compareSync("test123", hash1)); // display true
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-28 04:03:17
Implementacja bcrypt w innym języku może być różna.
Na przykład w Node.wersja js bcrypt.js , zastosowana długość soli to 29 znaków
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);
};
Ale w wersji Go golang.org/x/crypto/bcrypt , Rozmiar soli to 22 bajtów:
const (
majorVersion = '2'
minorVersion = 'a'
maxSaltSize = 16
maxCryptedHashSize = 23
encodedSaltSize = 22
encodedHashSize = 31
minHashSize = 59
)
Tak więc, może się zdarzyć, że hashed string w Node.js pobiera błąd podczas porównywania w Go, inne języki również.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-29 03:30:33