How to Hash a Password#

argon2-cffi comes with an high-level API and uses the officially recommended low-memory Argon2 parameters that result in a verification time of 40–50ms on recent-ish hardware.

Warning

The current memory requirement is set to rather conservative 64 MB. However, in memory constrained environments such as Docker containers that can lead to problems. One possible non-obvious symptom are apparent freezes that are caused by swapping.

Please check Choosing Parameters for more details.

Unless you have any special requirements, all you need to know is:

>>> from argon2 import PasswordHasher
>>> ph = PasswordHasher()
>>> hash = ph.hash("correct horse battery staple")
>>> hash  
'$argon2id$v=19$m=65536,t=3,p=4$MIIRqgvgQbgj220jfp0MPA$YfwJSVjtjSU0zzV/P3S9nnQ/USre2wvJMjfCIjrTQbg'
>>> ph.verify(hash, "correct horse battery staple")
True
>>> ph.check_needs_rehash(hash)
False
>>> ph.verify(hash, "Tr0ub4dor&3")
Traceback (most recent call last):
...
argon2.exceptions.VerifyMismatchError: The password does not match the supplied hash

A login function could thus look like this:

import argon2


ph = argon2.PasswordHasher()


def login(db, user, password):
    hash = db.get_password_hash_for_user(user)

    # Verify password, raises exception if wrong.
    ph.verify(hash, password)

    # Now that we have the cleartext password,
    # check the hash's parameters and if outdated,
    # rehash the user's password in the database.
    if ph.check_needs_rehash(hash):
        db.set_password_hash_for_user(user, ph.hash(password))

While the argon2.PasswordHasher class has the aspiration to be good to use out of the box, it has all the parametrization you’ll need.