I'm in a situation where a Node app and a PHP app are sharing a database. 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.

There are multiple versions of bcrypt: https://en.wikipedia.org/wiki/Bcrypt#Versioning_history

PHP uses $2y$ while this NPM module uses $2a$. They are still compatible though, so we can just replace this part of the hash.

Example

password.php:

<?php

$password = "qwertyuiop";

$hash = password_hash($password, PASSWORD_BCRYPT);
// PASSWORD_DEFAULT is equivalent as of now
// https://www.php.net/manual/en/function.password-hash.php

echo $hash;

password.js:

const bcrypt = require('bcrypt');
const exec = require('child_process').exec

const password = 'qwertyuiop';

const cmd = '/usr/local/bin/php ./password.php'

exec(cmd, (err, stdout, stderr) => {
    // See https://en.wikipedia.org/wiki/Bcrypt#Versioning_history
    const hash = stdout.replace('$2y$', '$2a$');

    bcrypt.compare(password, hash).then(function(res) {
        // Should output true
        console.log(res);
    });
});

It's working 👍

[email protected] ~/l/password-hash> node password.js
true

The reverse operation can of course be done using the same technique.

Source: Stack Overflow