Search code examples
pythonflaskbcrypt

using bcrypt password hashing for user authentication


I am trying to use hashed passwords in my app, like this:

class UserService():

    def register_user(self, username, email, password):
        if self.__checkIfUserExists(username) is True:
            return False
        else:

            hashed_password = self.__hash_password(password.encode('utf-8'), bcrypt.gensalt())

            user = User(username=username, email=email, password_hash=hashed_password)

            db.session.add(user)
            db.session.commit()
            db.session.close()

        return True

    def authenticate_user(self, email, password):
        user = User.query.filter_by(email=email).first()
        hashed_pw = self.__hash_password(password.encode("utf-8"), bcrypt.gensalt())
        print(hashed_pw == user.password_hash)
        if user and hashed_pw == user.password_hash:
            return True
        return False


    def __checkIfUserExists(self, username):
        exists = db.session.query(db.exists().where(User.username== username)).scalar()
        return exists

    def __hash_password(self, password, salt):
        return bcrypt.hashpw(password, salt)

Well, the passwords never match.

How do I get this to work? Where is my mistake? I thought I had to compare the hash of the provided password with the hash stored in the database..?


Solution

  • From https://pypi.python.org/pypi/bcrypt/2.0.0:

    >>> import bcrypt
    >>> password = b"super secret password"
    >>> # Hash a password for the first time, with a randomly-generated salt
    >>> hashed = bcrypt.hashpw(password, bcrypt.gensalt())
    >>> # Check that a unhashed password matches one that has previously been
    >>> #   hashed
    >>> if bcrypt.hashpw(password, hashed) == hashed:
    ...     print("It Matches!")
    ... else:
    ...     print("It Does not Match :(")
    

    Note that hashpw takes in either a salt or a previously hashed password (which includes the salt that was used to create it) allowing proper comparison.

    You've used bcrypt.gensalt() twice which creates two different random salts, so the hashes will be different.