Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing BCrypt hash between PHP and NodeJS

For an app I'm working on, nodejs needs to verify hashes created by PHP and vice-versa.

The problem is, the hashes generated in PHP (via Laravel's Hash class, which just uses PHP's password_hash function) return false when tested in node.js.

The following node.js script:

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', whereas the following PHP script:

<?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'; 

outputs 'PHP passed nodejs passed'.

I've run the tests in Ubuntu 14.04.1 using PHP 5.5.18, node.js v0.10.32 and the npm bcrypt module.

like image 823
wolfemm Avatar asked Oct 30 '14 01:10

wolfemm


People also ask

How does bcrypt compare with PHP password?

The PHP app handles the user registration and hashes the password using password_hash() . The password_hash() function uses the bcrypt algorithm if you specify PASSWORD_DEFAULT or PASSWORD_BCRYPT . With Node, the bcrypt NPM module can be used to compare the hash and the plain password, with a little gotcha.

How does node JS compare with bcrypt password?

Check A User Entered Password const bcrypt = require("bcryptjs") const passwordEnteredByUser = "mypass123" const hash = "YOUR_HASH_STRING" bcrypt. compare(passwordEnteredByUser, hash, function(err, isMatch) { if (err) { throw err } else if (! isMatch) { console. log("Password doesn't match!") } else { console.

What's the difference between bcrypt and hash?

The principal difference - MD5 and other hash functions designed to verify data have been designed to be fast, and bcrypt() has been designed to be slow. When you are verifying data, you want the speed, because you want to verify the data as fast as possible.

Is bcrypt asynchronous comparison?

Yes. You are completely right. But it could be more comfortable to use async/await syntax. So you will not appear in a callback hell at some moment ).


Video Answer


2 Answers

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

like image 170
majidarif Avatar answered Oct 13 '22 13:10

majidarif


I have tried to compute what was said before to get codes that work. As you can see I don't need to replace anything.

On the PHP 7.2.4 side:

<?php $password = "test123";     $hash = password_hash($password, PASSWORD_BCRYPT);     echo $hash; // I get $2y$10$5EaF4lMSCFWe7YqqxyBnR.QmDu1XhoiaQxrOFw.AJZkGCYmpsWDU6 

On the nodeJS side:

Install bcryptjs package: npm i bcryptjs

var bcrypt = require('bcryptjs'); let hash1="$2y$10$5EaF4lMSCFWe7YqqxyBnR.QmDu1XhoiaQxrOFw.AJZkGCYmpsWDU6"; console.log(bcrypt.compareSync("test123", hash1)); // display true 
like image 23
Nicolas Guérinet Avatar answered Oct 13 '22 14:10

Nicolas Guérinet