I'm trying to port a legacy password hashing scheme from PHP to Javascript (node.js), but I'm missing something in the process.
Original, working PHP version
Here is the "original", working code:
function create_hash($password) {
$salt = uniqid();
$algorithm = '6'; // CRYPT_SHA512
$rounds = '1234';
// This is the "salt" string we give to crypt().
$cryptSalt = '$' . $algorithm . '$rounds=' . $rounds . '$' . $salt;
$hashedPassword = crypt($password, $cryptSalt);
return $hashedPassword;
}
function hash_is_valid($password, $hash) {
return (crypt($password, $hash) == $hash);
}
Working test with above PHP functions:
echo $password = 'secret';
echo '<br /><br />';
echo $hash = create_hash($password);
echo '<br /><br />';
echo 'Should be true: ';
$valid1 = hash_is_valid($password, $hash);
var_dump($valid1); // outputs "bool(true)"
echo '<br /><br />';
echo 'Should be false: ';
$valid2 = hash_is_valid('wrong_pass', $hash);
var_dump($valid2); // outputs "bool(false)"
echo '<br /><br />';
Javascript Version (broken)
Here's what I've got so far, but it isn't quite there
function hash_is_valid(password, hash, cb) {
// Hash Format:
// $[algorithm]$[number_of_rounds]$[salt]$[hashed_password]
let hashParts = hash.split('$')
console.log(hashParts)
let salt = hashParts[3]
let numRounds = parseInt(hashParts[2].substr(7)) // from string like rounds=1234
let originalHashResult = hashParts[4]
let salted = password + '{' + salt + '}'
let processedHash = crypto.createHash('sha512').update(salted, 'utf-8');
for (let i = 1; i < numRounds ; i++) {
processedHash = crypto.createHash('sha512').update(processedHash.digest('binary') + salted);
}
processedHash = processedHash.digest('base64')
// Capture the result
let hashVerified = (processedHash === originalHashResult)
// Call the callback with the result
cb(hashVerified)
}
hash_is_valid('secret', '$6$rounds=1234$56ab50921c460$P4bgd3kMX2xyWJTDOYAdow.jsXiS2TARUJW4BXifgm4czraOIDFLqZ5Ii50GLIKwYTjWwN6WrtG82omQes0cK0', (passed) => {
console.log((passed) ? 'password is good' : 'password is no good')
})
javascript based on answer to SO question How to validate Symfony2 sha512 passwords using nodejs
The javascript version is using some test values:
password: secret
hash: $6$rounds=1234$56ab50921c460$P4bgd3kMX2xyWJTDOYAdow.jsXiS2TARUJW4BXifgm4czraOIDFLqZ5Ii50GLIKwYTjWwN6WrtG82omQes0cK0
numRounds - 1times since it starts with 1.nyqekS7RsL62iyBLbCtO9OTKPmNvO1n9mq7yZA15E7x3URU7YN1qsWYjAErujvptidcp1+nYytx4wJGSsAjX0A==