Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The the output of `bcrypt(password)` is:

  $2a$12$R9h/cIPz0gi.URNNX3kh2OPST9/PgBkqquzi.Ss7KIUgO2t0jWMUW
  \__/\/ \____________________/\_____________________________/
  Alg Cost      Salt                        Hash
The Salt part is randomly generated. When you call `bcrypt.compare(output, password)` it uses the salt that's contained in `output`. Two calls of `bcrypt(password)` will generate different outputs(so different salts and thus different hashes), but still if you run `bcrypt.compare(output1, password)` and `bcrypt.compare(output2, password)` they will both match as long `password` was used to generate both.

In short: you can't use just the password as that's going to match a cache key that was generated by whoever typed in this exact password. The salt is only there to prevent offline attacks.



But if you're using bcrypt to compute a dictionary lookup key, you're not going to use bcrypt.compare as it would require a linear scan and be slow as a snail.

Rather you use the bcrypt output itself as the lookup key. And if you do that then the salt will indeed do what it's designed to do.

The function you used is a convenience function which generates random salt, but you can specify your own as is done in this[1] illustration of the Okta incident.

What bcrypt.compare does is essentially to extract the salt from the provided previous output, compute new hash using that and the provided password, and check that the old and new hashes matches.

As such it's equivalent to comparing the outputs of two different "runs" where the same salt is used (modulo timing attacks).

So if you need to recompute the lookup key then you need to use the same salt value.

[1]: https://kondukto.io/blog/okta-vulnerability-bcrypt-auth




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: