user2882590 user2882590 - 2 years ago 121
Node.js Question

How to compare hashed values with the JavaScript library password-hash?

Short version:

I would like to know if the same value is hashed with random salts, how can I verify if the one that I got now is "equal" to the one that's already in my database, stored as the users password. Also what does equal mean here?

Long version:

Until now I thought that hash functions work like this when passwords have to be hashed:

  • Choose an algorithm, let's say it's SHA1

  • Use that algorithm to change the input so much that you can't guess what was the input or how did it look like

  • Put the hashed value into the database with the user and when login is needed use the hash function again on input and match it with the one that's already in the database

  • It is suggested to use random salts, store them alongside users and during login phase, you take out that salt to hash the given password and match it with the hashed value already in the database.

So, I have the following code in Node.js

var passwordHash = require('password-hash');

var foo = passwordHash.generate('password123');
var bar = passwordHash.generate('password123');

console.log(foo); //sha1$d1d19f32$1$d5cb099afdd9bb130c969e0394c9bf5e57d6a2aa
console.log(bar); //sha1$df372235$1$99dfd5485e8a223e21738621bf4a7cdfca949721

console.log(passwordHash.verify('password123', foo)); //true
console.log(passwordHash.verify('password123', bar)); //true

I know that
uses random salt, it's the part between
. I can't find in the documentation that the salt is stored somewhere, and if it is, why isn't identical for the two hashed values?

I thought that
and checks if it's identical to
and alternatively
. However this can't happen because I always get true, but
are different.

So how does

Answer Source

The salt is included in the string that is returned by generate separated by $ chars:


alg $ salt $ hash

Looking at the source for password-hash all you should have to do is call the verify method on the resulting string that contains the $'s and salt.

This is their verify function:

module.exports.verify = function(password, hashedPassword) {
  if (!password || !hashedPassword) return false;
  hashedPassword = makeBackwardCompatible(hashedPassword);
  var parts = hashedPassword.split('$');
  if (parts.length != 4) return false;
  try {
    return generateHash(parts[0], parts[1], password, parts[2]) == hashedPassword;
  } catch (e) {}
  return false;

As you can see it splits the input string on the $, and then generates the hash with the salt and compares to the password. This means that you should call the verify method with the entire string that the origional generate method returned just as you are doing in your question.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download