Verify Password Hash in Nodejs Which Was Generated in PHP

How to verify a PHP hashed password in a NodeJS app

Use bcryptjs package instead. It can compare php generated hashes correctly.

const bcrypt = require('bcryptjs')

const hashPHP = "$2y$10$Lsn001yN38WssfQmJ5hM5.Ywa3AKB76YD/zUC9QNS5BPRr9QMWOTa"
console.log(bcrypt.compareSync("my password", hashPHP)); // outputs: true

Password(+salt) hashing and verifying in PHP and/or NodeJS

To hash a password in PHP:

$hash = password_hash($password, PASSWORD_BCRYPT);

This generates a hash with $2y$ that you need to store in the database. Use this code to compare the password in Node:

bcrypt.compare(password_from_input, password_from_db.replace(/^\$2y(.+)$/i, '\$2a$1'), function(err, result) {
console.log(result);
});

To hash a password in Node:

bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(password_from_input, salt, function(err, hash) {
hash = hash.replace(/^\$2a(.+)$/i, '\$2y$1');
//Insert into database
});
});

This generates a hash with $2a$. The example above replaces it with $2y$, so comparing will be easier in PHP.

To compare a password in PHP:

if (password_verify($password_from_input, $hash)) {
echo 'Password is valid!';
} else {
echo 'Invalid password.';
}

Comparing BCrypt hash between PHP and NodeJS

This fails because the types of bcrypt hashes being generated from php and node are different. Laravel generates the $2y$ while node generates the $2a$. But the good news is the only difference between 2a and 2y are their prefixes.

So what you can do is make one of the prefix similar to the other. Like:

$phpGeneratedHash  = '$2y$10$jOTwkwLVn6OeA/843CyIHu67ib4RixMa/N/pTJVhOjTddvrG8ge5.';
$nodeGeneratedHash = '$2a$10$ZiBH5JtTDtXqDajO6f4EbeBIXGwtcGg2MGwr90xTH9ki34SV6rZhO';

To something like:

$phpGeneratedHash  = '$2y$10$jOTwkwLVn6OeA/843CyIHu67ib4RixMa/N/pTJVhOjTddvrG8ge5.';
$nodeGeneratedHash = '$2y$10$ZiBH5JtTDtXqDajO6f4EbeBIXGwtcGg2MGwr90xTH9ki34SV6rZhO';

Notice that I replaced the $2a$ of the node hash to $2y$. You can simply do this with:

PHP

$finalNodeGeneratedHash = str_replace("$2a$", "$2y$", $nodeGeneratedHash);

Node

finalNodeGeneratedHash = nodeGeneratedHash.replace('$2a$', '$2y$');

Then compare phpGeneratedHash to finalNodeGeneratedHash.

Note: It is recommended that if you're comparing in PHP, change the prefix of the NodeJS generated hash to $2y$ and if you're comparing in NodeJS; change the prefix of the PHP generated hash to $2a$.

NODE.JS - How to check a Laravel hashed password with bcrypt?

I fond the answer here. It's way easier than I thought.

var hash = '$2y$08$9TTThrthZhTOcoHELRjuN.3mJd2iKYIeNlV/CYJUWWRnDfRRw6fD2';
var bcrypt = require('bcrypt');
hash = hash.replace(/^\$2y(.+)$/i, '$2a$1');
bcrypt.compare("secret", hash, function(err, res) {
console.log(res);
});

Compare Nodejs generated bcrypt hash in PHP

You shouldn't expect them to match, at least by default. This is because for both functions, a random salt is chosen every time you hash a value.

The important thing is not that the hash outputs match, but that they still validate. So you could take the hashed output from node.js and use it with password_verify() in PHP for example, and it should validate.



Related Topics



Leave a reply



Submit