27

When I run werkzeug.security.generate_password_hash("Same password") (docs) multiple times, the output is different each time.

What am I doing wrong? Why is it not constant?

Martin Thoma
  • 91,837
  • 114
  • 489
  • 768
Shankar ARUL
  • 9,495
  • 8
  • 59
  • 62
  • 1
    Turns out i was truncating it when i was storing it in my database. As a result, i couldnt compare it properly :-) – Shankar ARUL Jun 10 '14 at 13:28
  • 1
    Thanks for asking this question - I was rehashing in order to do the comparison instead of using the check_password_hash() method. Wouldn't have known to do otherwise but for the answer to the question. Upvote for both of you. – JakeJ Oct 30 '17 at 17:58

1 Answers1

60

The password is salted, yes. The salt is added to the password before hashing, to ensure that the hash isn't useable in a rainbow table attack.

Because the salt is randomly generated each time you call the function, the resulting password hash is also different. The returned hash includes the generated salt so that can still correctly verify the password.

Demo:

>>> from werkzeug.security import generate_password_hash
>>> generate_password_hash('foobar')
'pbkdf2:sha1:1000$tYqN0VeL$2ee2568465fa30c1e6680196f8bb9eb0d2ca072d'
>>> generate_password_hash('foobar')
'pbkdf2:sha1:1000$XHj5nlLU$bb9a81bc54e7d6e11d9ab212cd143e768ea6225d'

These two strings differ; but contain enough information to verify the password because the generated salt is included in each:

# pbkdf2:sha1:1000$tYqN0VeL$2ee2568465fa30c1e6680196f8bb9eb0d2ca072d
  ^^^^^^^^^^^^^^^^   salt   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      algo info    ^^^^^^^^        actual hash of the password
  (PBKDF2 applied SHA1 1000 times)

Because the random salt is tYqN0VeL for one and XHj5nlLU, the resulting hash is also different.

The foobar password can still be verified against either hash:

>>> from werkzeug.security import check_password_hash
>>> check_password_hash('pbkdf2:sha1:1000$tYqN0VeL$2ee2568465fa30c1e6680196f8bb9eb0d2ca072d', 'foobar')
True
>>> check_password_hash('pbkdf2:sha1:1000$XHj5nlLU$bb9a81bc54e7d6e11d9ab212cd143e768ea6225d', 'foobar')
True

Also see

Community
  • 1
  • 1
Martijn Pieters
  • 889,049
  • 245
  • 3,507
  • 2,997