Update
Starting with version 3.1.0 bcrypt
provides a convenient function
checkpw(password, hashed_password)
Perform password verification with a hashed password. This should be used instead:
bcrypt.hashpw(passwd_to_check, hashed_passwd) == hashed_passwd
which is shown below. There is still no need to store the hash separately.
First of all, you do not need to store salt, because it is part of the hash generated by bcrypt.hashpw()
. You just need to save the hash. For instance.
>>> salt = bcrypt.gensalt() >>> salt b'$2b$12$ge7ZjwywBd5r5KG.tcznne' >>> passwd = b' p@ssw0rd ' >>> hashed_passwd = bcrypt.hashpw(passwd, salt) b'$2b$12$ge7ZjwywBd5r5KG.tcznnez8pEYcE1QvKshpqh3rrmwNTQIaDWWvO' >>> hashed_passwd.startswith(salt) True
So you can see that salt is included in the hash.
You can also use bcrypt.hashpw()
to verify that the password matches the hashed password:
>>> passwd_to_check = b' p@ssw0rd ' >>> matched = bcrypt.hashpw(passwd_to_check, hashed_passwd) == hashed_passwd >>> matched True >>> bcrypt.hashpw(b'thewrongpassword', hashed_passwd) == hashed_passwd False
No need to store salt separately.
So you can write setter like this (Python 3):
@password.setter def password(self, passwd): if isinstance(passwd, str): passwd = bytes(passwd, 'utf-8') self.passwd = str(bcrypt.hashpw(passwd, bcrypt.gensalt()), 'utf8')
And a checker like this:
def check_password(self, passwd_to_check): if isinstance(passwd_to_check, str): passwd_to_check = bytes(passwd_to_check, 'utf-8') passwd = bytes(self.passwd, 'utf8') return bcrypt.hashpw(passwd_to_check, passwd) == passwd