📝 Python

Password Hashing: bcrypt and passlib

P
Author
Pyland
📅
Published
30.06.2026
⏱️
Reading time
1 min
👁️
Views
187
🌳
Level
Advanced

If the database is leaked, an attacker gains access to every password. Hashing makes this impossible.

Why you must not store passwords in plain text

If the database is leaked, an attacker gains access to every password. Hashing makes this impossible.

pip install passlib[bcrypt]
from passlib.context import CryptContext

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

# Hash a password
hashed = pwd_context.hash("my_password")
# '$2b$12$...' — bcrypt hash

# Verify a password
is_valid = pwd_context.verify("my_password", hashed)   # True
is_valid = pwd_context.verify("wrong_password", hashed) # False

Why bcrypt

  • Intentionally slow (10–12 hashing rounds)
  • Built-in salt — identical passwords produce different hashes
  • Configurable cost factor — can be increased over time
  • Resistant to brute-force attacks and rainbow tables

In FastAPI / SQLModel

from passlib.context import CryptContext

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

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=pwd_context.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 pwd_context.verify(password, user.hashed_password):
        return None
    return user

argon2 — an alternative to bcrypt

pip install passlib[argon2]
pwd_context = CryptContext(schemes=["argon2"], deprecated="auto")

Argon2 won the Password Hashing Competition in 2015 and is recommended for new projects.

Your reaction to the article

💬 Comments (0)

🔐 Sign in to leave a comment
🚪 Login
💭

No comments yet

Be the first to share your opinion about this article!

🔗 Similar

Similar articles

Continue learning with these materials

📝

Event Loop in Python: How asyncio Achieves "Paral…

Event loop is the heart of asyncio. It doesn't run code in parallel across multiple...

📅 30.06.2026 👁️ 123
📝

pytest-django: Testing Django

Охватываемые темы: Installation, @pytest.mark.djangodb, Fixtures, Testing views.

📅 30.06.2026 👁️ 132
📝

pip: Python Package Manager

Охватываемые темы: Installing packages, Upgrading and removing, requirements.txt, Virtual environment.

📅 30.06.2026 👁️ 120

Did you like the article?

Subscribe to our updates and receive new articles first. Grow with PyLand!