Storing and verifying passwords with SQLAlchemy
I really enjoy abstractions.
Abstractions are the lifeblood of programming. They take complex operations and make them easy to work with through accessible interfaces. This article will be about doing that with the way we store and verify passwords (or rather their cryptographic hashes) in (web-)applications based on SQLAlchemy. And in such a way that we can upgrade the security of passwords as old encryption schemes are broken or proven insufficient and new ones get introduced.
The ways of verifying passwords
There are many different ways to deal with password verification, but they can be classified in three rough categories:
Ad-hoc verification
This approach is often used for one-off scripts or trivial applications that have a single verification and have very little to gain from reusable components. The following shows a very basic User model and password verification code:
import bcrypt
from sqlalchemy import Column, Integer, Text
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(Text)
password = Column(Text)
pwhash = bcrypt.hashpw(login_data['password'], user.password)
if user.password == pwhash:
print 'Access granted'
The snippet above uses the Python bcrypt package for key derivation, but you may well use another key derivation method, like PBKDF2 or scrypt. To be sure: It should not have a static salt, and it should definitely not be a single round of optimized-for-speed SHA1 or SHA2 functions. [1] In short, use proven and existing methods.
Assuming that the hashing algorithm is secure, this code is perfectly fine for the stated goal. However, most applications are not trivial and most one-off scripts tend to find their way into repeated use. And over time you find yourself confronted with more and more repeats of the same code to verify a user’s password. Something needs to be done, it’s time to …