If a database is leaked, strong password hashing prevents immediate recovery of plaintext passwords and makes offline guessing expensive. It does not make weak passwords impossible to crack, so password policy, rate limiting, and multi-factor authentication still matter.
Why you must not store passwords in plain text
Store only salted password hashes, never plaintext passwords. For new applications, use a maintained password-hashing library and its recommended algorithm and parameters.
pwdlib with Argon2
uv add "pwdlib[argon2]"
from pwdlib import PasswordHash
password_hash = PasswordHash.recommended()
# Hash a password
hashed = password_hash.hash("my_password")
# '$argon2id$...' โ Argon2id hash
# Verify a password
is_valid = password_hash.verify("my_password", hashed) # True
is_valid = password_hash.verify("wrong_password", hashed) # False
Why Argon2id
- Designed for password hashing and resistant to GPU-based guessing
- Uses a unique salt, so identical passwords produce different hashes
- Has configurable time, memory, and parallelism costs
PasswordHash.recommended()selects maintained recommended settings
In FastAPI / SQLModel
from pwdlib import PasswordHash
password_hash = PasswordHash.recommended()
class User(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
username: str = Field(unique=True)
hashed_password: str
def create_user(session: Session, username: str, password: str) -> User:
user = User(
username=username,
hashed_password=password_hash.hash(password),
)
session.add(user)
session.commit()
return user
def authenticate(session: Session, username: str, password: str) -> User | None:
user = session.exec(select(User).where(User.username == username)).first()
if not user or not password_hash.verify(password, user.hashed_password):
return None
return user
Existing bcrypt hashes
uv add "pwdlib[argon2,bcrypt]"
Argon2id is the preferred choice for new hashes. If an existing system already contains bcrypt hashes, configure a migration path that verifies the legacy hash and replaces it with Argon2id after the user’s next successful login. Do not silently change algorithms without testing compatibility with stored hashes.
๐ฌ Comments (0)
No comments yet
Be the first to share your opinion about this article!