13. Passwords & Cryptography
Passwords & Cryptography
If your database has a column called password and it contains values like password123 or qwerty — your application is critically and immediately dangerous. Every week, major companies suffer data breaches. When hackers steal a database, the first thing they do is harvest the passwords. If those passwords are stored in plain text, every single user's account on every other website they use is now compromised. This module is not optional knowledge — it is a professional and ethical responsibility.
Why You Must NEVER Store Plain-Text Passwords
Here are the concrete risks of plain-text password storage:
- Database breach: Any SQL injection vulnerability, any malicious employee, any backup file left unsecured — instantly exposes every user's password.
- Password reuse: Studies show over 65% of people reuse passwords. Stealing your database gives attackers access to users' email, banking, and social media accounts.
- Legal liability: GDPR in Europe and data protection laws in many countries make storing passwords in plain text a regulatory violation that results in massive fines.
- Trust destruction: Once it's revealed your company stored passwords in plain text, that reputation damage is permanent.
Never store the password. Store a one-way cryptographic transformation of it that can never be reversed.
Why Simple Hashing Is Also Not Enough
Your first instinct might be to hash the password with MD5 or SHA-256. This is better than plain text — but still dangerously insecure for passwords. Here's why:
- Rainbow tables: Attackers precompute a massive lookup table of millions of common passwords and their hashes. If your hash is in the table, the password is instantly known. SHA256("password123") is always the same hash, and it's in every rainbow table.
- Speed is an enemy: SHA-256 can compute billions of hashes per second on modern GPU hardware. A brute-force attack against a leaked SHA-256 database is trivially fast.
The solution requires two things: salting and purposefully slow hashing algorithms.
Salting
A salt is a long, random string generated uniquely for every user and appended to their password before hashing. This means even if two users have the identical password "cat123", they produce completely different hashes because each salt is different. It makes rainbow table attacks completely ineffective.
bcrypt — The Industry Standard for Password Hashing
bcrypt was specifically designed for hashing passwords. Unlike SHA-256 (built for speed), bcrypt is intentionally slow. It has a configurable work factor (called rounds or cost) that controls how many iterations of the algorithm run. More rounds = slower = harder to brute-force.
bcrypt also handles salting automatically — you don't manage the salt yourself. It generates a random salt, incorporates it into the hash computation, and stores the salt inside the resulting hash string. When verifying, bcrypt extracts the salt from the stored hash and re-runs the algorithm.
Password Hashing in Python
Password Reset — The Secure Way
When users forget their password, how do you reset it without exposing sensitive information? Never email the password itself (you can't — you don't have it). Never email a permanent link. The correct approach uses a short-lived cryptographic token:
Security Best Practices Summary
bcrypt for most apps. Argon2id is the newer recommendation — more resistant to GPU attacks.
10 was standard in 2015. As hardware gets faster, increase rounds. 12 is current best practice.
"Invalid email or password" — not "email not found" or "wrong password."
After 5 failed attempts, lock the account or add a CAPTCHA. Use express-rate-limit.
15 minutes maximum. Hash the token in the database. One-time use only.
Check against the HaveIBeenPwned API to reject known-breached passwords.
Knowledge Check
Ready to test your understanding of 13. Passwords & Cryptography?