liveBook · Manning

Cryptographic hash

As explained in The Well-Grounded Python Developer: How the pros use Python and Flask

A cryptographic hash is a one-way transformation that maps data to a fixed-format digest designed to make recovery of the original data computationally difficult.

A login system needs to check passwords without storing them in readable form. A cryptographic hash turns a password into a stored value that cannot be used to read back the original password. section 8.2.1

Keep that work inside the user model: setting `User.password` generates a cryptographically strong hash and stores it as `hashed_password`. Reading `User.password` raises an attribute error. When someone logs in, `verify_password()` checks the submitted password against the stored hash. section 8.2.1

class User(UserMixin, db.Model):                                          #1
    __tablename__ = "user"                                                #2
    user_uid = db.Column(db.String, primary_key=True, default=get_uuid)   #3
    first_name = db.Column(db.String, nullable=False)                     #4
    last_name = db.Column(db.String, nullable=False)                      #4
    email = db.Column(db.String, nullable=False,                          #4
    unique=True, index=True)                                            #4
    hashed_password = db.Column("password",                               #4
    db.String, nullable=False)                                          #4
    active = db.Column(db.Boolean, nullable=False, default=False)         #4
    created = db.Column(db.DateTime, nullable=False,                      #5
    default=datetime.utcnow)                                            #5
    updated = db.Column(db.DateTime, nullable=False,                      #5
    default=datetime.utcnow, onupdate=datetime.utcnow)                  #5
 
    def get_id(self):
        return self.user_uid
 
    @property
    def password(self):
        raise AttributeError("user password can’t be read")
 
    @password.setter
    def password(self, password):
        self.hashed_password = generate_password_hash(password)
 
    def verify_password(self, password):
        return check_password_hash(self.hashed_password, password)
 
    def __repr__(self):
        return f"""
        user_uid: {self.user_uid}
        name: {self.first_name} {self.last_name}
        email: {self.email}
        active: {'True' if self.active else 'False'}
        """

The model stores `hashed_password` in a database column named `password`; the attribute name makes its contents clearer in application code. section 8.2.1

How The Well-Grounded Python Developer: How the pros use Python and Flask covers it

How deep it goes
Explains model-level hashing and verification, but does not describe the hash algorithm or its internals.
Examples
Uses a `User` model with a write-only password property, a `hashed_password` attribute, and login-form verification.
What it assumes
Assumes familiarity with Python properties and Flask user models rather than teaching those constructs from zero.
What you can do after
Apply it via Flask-Bcrypt to store password hashes and check submitted passwords in a user model.
How it connects
Connects password hashing to authentication, model properties, database columns, and login forms.

Also explained in

Compare how 4 books explain cryptographic hash →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Well-Grounded Python Developer: How the pros use Python and Flask. The section links point to the parts of the book it draws on.