Melissa Stewart
Melissa Stewart

Reputation: 3605

Hashed password doesn't match original in Python

I've two rest endpoints, one that registers an user and the second that lets that user login. This is the code that I'm using to hash the user's password and store the hashed password in the database,

from passlib.hash import pbkdf2_sha256
def _get_hashed_password(self, password):
    return pbkdf2_sha256.encrypt(password, rounds=200000, salt_size=16)

Now on the login endpoint I use this code to verify the hashed password,

password = data['password']
hash = pbkdf2_sha256.encrypt(password, rounds=200000, salt_size=16)
pbkdf2_sha256.verify(user.hashed_password, hash)

This method fails and clearly because the two passwords are different,

$pbkdf2-sha256$200000$ai0FoDTG2BuDkDKGEIJQKg$Ik06dr61.2rRMDwZCZMdVq.zMe5887.ksDxvmSXFRwE
$pbkdf2-sha256$200000$pHTuHYNwLoXQeu8dI0QoxQ$2z4cZl9Njz9X/bxNtWCZzzeplWO.jTZA2v5lvcmgFE8

I'm wondering how can I get this to work?

Upvotes: -1

Views: 2267

Answers (1)

Blender
Blender

Reputation: 298046

pbkdf2_sha256.encrypt and pbkdf2_sha256.verify do more than just compute the hash of your password. Look closely at the output of pbkdf2_sha256.encrypt

$pbkdf2-sha256$200000$ai0FoDTG2BuDkDKGEIJQKg$Ik06dr61.2rRMDwZCZMdVq.zMe5887.ksDxvmSXFRwE
----------------------------------------------------------------------------------------
$  algorithm  $rounds$         salt         $             the actual hash

You can switch algorithms, increase the number of rounds in a few years, and pbkdf2_sha256.verify will still be able to verify a plaintext password against the hash stored in your database.

Hashing the same password twice will not give you the same result each time because a random salt is used. The salt prevents rainbow table attacks in the event an attacker gains access to your password hashes. Basically, instead of computing just hash(password), you compute something like hash(salt + password). Since the salt is already given in the above string and you presumably know the password, you will also know the value of salt + password and your life won't be any more difficult. But for an attacker that spent a lot of time pre-computing just hash(password), none of those hashes will be useful because they don't incorporate your random salt.

As in the example posted in the comments, you don't need to do anything special to verify your passwords:

pbkdf2_sha256.verify(password, user.hashed_password)

There's no need to call pbkdf2_sha256.encrypt when verifying a password. pbkdf2_sha256.verify does all of this for you.

Upvotes: 7

Related Questions