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.

Author: majidarif, 2014-10-30

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$.

 71
Author: majidarif,
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
 4
Author: Nicolas Guérinet,
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ż.

 0
Author: S.K.,
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