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
Mp4 Plays When Accessed Directly, But Not When Read Through PHP, on iOS
How to Check If a MySQL Query Using the Legacy API Was Successful
PHP - Create Simple Animated Gif from Two Jpeg Images
PHP - Detect Whitespace Between Strings
Dirt-Simple PHP Templates... Can This Work Without 'Eval'
Unexpected 'Use' (T_Use) When Trying to Use Composer
Avoiding MySQL Injections with the Zend_Db Class
Rendering an Svg File to a Png or Jpeg in PHP
Regex - How to Insert String Before File Extension
How to Upload Multiple Image in Laravel
Confusion Between Bindvalue() and Bindparam()
Remove Non English Characters PHP
Ios7 - Receipts Not Validating at Sandbox - Error 21002 (Java.Lang.Illegalargumentexception)
How to Remove Values from Two Arrays That Have the Same Key and Value