Verify password hash in nodejs which was generated

2019-02-01 16:08发布

问题:

My php code generates a hash using password_hash which I store in a database. Below is the PHP code:

$hash = password_hash($value, PASSWORD_BCRYPT, array('cost' => $cost));

I would like to verify / check the password against this hash in nodejs.

I saw lot of node modules (bcrypt, phpass, node-bcrypt), but all of them give me false. Below is sample hash generated in php and which I m trying to verify in nodejs.

var hash = '$2y$08$9TTThrthZhTOcoHELRjuN.3mJd2iKYIeNlV/CYJUWWRnDfRRw6fD2';

var bcrypt = require('bcrypt');

bcrypt.compare("secret", hash, function(err, res) {
    console.log(res);
});

(Here secret is real password)

My current workaround is to call a php script via node to verify (for anybody who needs a workaround)

var exec = require('child_process').exec;
var cmd = 'php verify.php password encryped_pasword';
exec(cmd, function (error, stdout, stderr) {
  // output is in stdout
  console.log(stdout);
 //If stdout has 1 it satisfies else false
});

This is a hack and not a good answer to this problem. Is there a way to verify the password in nodejs without using a workaround like this?

回答1:

Replace $2y$ in the hashed password with $2a$,then bcrypt.compare should give you correct result.

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);
});

on ES6:

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


回答2:

I know this has been answered, but it seems from the comments that a little more detail is required.

Bcrypt hashes produced by the php password_hash() function are split as follows:

$2y$ 08$ 9TTThrthZhTOcoHELRjuN. 3mJd2iKYIeNlV/CYJUWWRnDfRRw6fD2

|     |     |                     |
|     |     Salt                  Hashed Password
|     |
|     Algorithm options (cost, in this case)
|
Algorithm type

It seems from other answers here on SO that while the PHP and Node versions of Bcrypt use different algorithms, the only difference in the hash output is the prefix. So all that is required is, as mentioned by @Sudesh, to swap the $2y$ for a $2a$ and Bob's your uncle.

Sources

http://php.net/manual/en/faq.passwords.php

$2y bcrypt hashes in Node.js

Comparing BCrypt hash between PHP and NodeJS