11

I am trying to use bcryptjs to generate hash of user passwords. However I am a bit confused in one matter.

Conventionally, according to this article, we need to:

  • keep the salt of our password hash relatively long and unique,
  • hash the user password salted with this salt
  • store the salted hashed password along with the salt

So when we are comparing the hash while authenticating the user, we append the stored salt to user inputed password, and compare it with hash from database.

However using hashSync and compareSync of bcryptjs as follows:

//hashSync to generate hash
var bcrypt = require('bcryptjs');
var password = "abc";
var hash = bcrypt.hashSync( <some string>, < integer length of salt>) // the salt of mentioned length(4-31) is self-generated which is random and fairly unique

//compareSYnc to compare hash
var testString="abc";
console.log(bcrypt.compareSync(testString, hash)) // compares with previously generated hash returns "true" in this case.

What I am confused is, if we dont need the salt while authenticating, what is significance of generating it? compareSync returns true without the access of salt. So wouldnt it make bruteforce attack for comparatively small password easy? All of the following returns true regardless of salt size:

console.log(bcrypt.compareSync("abc", bcrypt.hashSync("abc"))); // consoles true. by default, if salt size is not mentioned, size is 10.
console.log(bcrypt.compareSync("abc", bcrypt.hashSync("abc", 4))); //consoles true
console.log(bcrypt.compareSync("abc", bcrypt.hashSync("abc", 8))); //consoles true
console.log(bcrypt.compareSync("abc", bcrypt.hashSync("abc", 32))); //consoles true
console.log(bcrypt.compareSync("ab", bcrypt.hashSync("abc", 4))); //consoles false

I hope I am clear enough in explaining my confusion.

Pravin
  • 1,671
  • 5
  • 23
  • 36

1 Answers1

11

The bcrypt standard makes storing salts easy - everything it needs to check a password is stored in the output string.

The prefix "$2a$" or "2y" in a hash string in a shadow password file indicates that hash string is a bcrypt hash in modular crypt format. The rest of the hash string includes the cost parameter, a 128-bit salt (base-64 encoded as 22 characters), and the 192-bit[dubious – discuss] hash value (base-64 encoded as 31 characters).

That's from the Wikipedia page on bcrypt.

Aaron Dufour
  • 17,288
  • 1
  • 47
  • 69
  • my understanding of salt, as I mentioned from the article above, is it also concatenates to original password, so even very short passwords are difficult to crack using brute force. for eg: if password is "a" and salt is 32 characters long, bruteforce is to be done to 33 characters right? but using bcrypt, if salt is not stored, then any original character is matched, regardless of salt length. like first try for "a" gives true, regardless of salt length. So what is the use of salt in bcrypt if it is not stored, except for stopping rainbow table and reverse lookup table attacks? – Pravin Jan 02 '15 at 06:48
  • 6
    @Pravin The difference between hashing a 1 character password and a 33 character password is minimal to nothing. The salt _is_ stored - it's just stored in the same string that contains the hash. Salts only prevent rainbow table attacks. That's all they're for. – Aaron Dufour Jan 02 '15 at 07:06