Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes
Sponsored Reserved space — layout preview until AdSense is connected

Python

Secure Password Hashing in Python: Moving Beyond Plain Text

Learn why you should never store passwords in plain text and how to implement industry-standard hashing using bcrypt and Argon2 to protect user data from breaches.

June 2026 · 5 min read · 1 views · 0 hearts

Stop storing passwords in plain text. If you are doing this, you aren't just making a mistake; you are leaving the front door to your user data wide open for any attacker who manages to breach your database.

In the world of cybersecurity, the goal isn't to make a password "unhackable"—because given enough time and computing power, almost anything can be cracked. The goal is to make the cost of cracking a password so high that the attacker gives up.

Here is how to implement professional-grade password hashing and security in Python.

Why Hashing is Not Encryption

A common misconception is that password hashing is a form of encryption. It is not.

Encryption is a two-way street. You encrypt data to hide it, and you decrypt it later using a key to get the original data back. If a hacker steals your decryption key, they have every single user password in plain text.

Hashing is a one-way cryptographic function. It takes an input and turns it into a fixed-length string of characters (a digest). You cannot "de-hash" a password to see what the original was. When a user logs in, you hash their input and compare it to the hash stored in your database. If they match, the password is correct.

The Danger of "Fast" Hashes

Many developers reach for hashlib and use MD5 or SHA-256. While these are great for checking if a file is corrupted (checksums), they are disastrous for passwords.

Modern GPUs can calculate billions of SHA-256 hashes per second. An attacker with a "rainbow table" (a precomputed list of millions of common passwords and their corresponding hashes) can crack a simple SHA-256 password in milliseconds.

To secure passwords, you need slow hashes. You want a function that is computationally expensive, forcing the attacker to spend significant time and hardware resources on every single guess.

The Gold Standard: Argon2 and bcrypt

For Python developers, the industry standard is to use libraries designed specifically for password storage.

1. Argon2

Argon2 is the winner of the Password Hashing Competition and is currently considered the most secure choice. It is resistant to GPU-based attacks because it requires not just CPU time, but also a configurable amount of memory.

2. bcrypt

Bcrypt has been the reliable workhorse of the industry for decades. It incorporates a "work factor" (cost) that you can increase as hardware gets faster, ensuring your hashes remain slow enough to deter attackers.

Implementation Guide: Using bcrypt

The bcrypt library is widely supported and easy to implement. First, install it via pip: pip install bcrypt.

Hashing a Password

When a user creates an account, you generate a salt (a random string added to the password) and hash the result. bcrypt handles the salt automatically and embeds it into the final hash string.

import bcrypt

password = "my_super_secret_password123".encode('utf-8')

# Generate a salt and hash the password
# The salt is automatically included in the hashed result
hashed = bcrypt.hashpw(password, bcrypt.gensalt())

print(hashed) 
# Output looks like: b'$2b$12$K8... (a long string)'

Verifying a Password

During login, you retrieve the stored hash from your database and compare it to the password the user just entered.

user_input = "my_super_secret_password123".encode('utf-8')

if bcrypt.checkpw(user_input, hashed):
    print("Login successful!")
else:
    print("Invalid password.")

Security Best Practices Checklist

Implementing a hashing library is only half the battle. To truly secure user accounts, follow these guidelines:

1. Never Roll Your Own Crypto

Never try to write your own hashing algorithm or create a "custom" way of salting passwords. Cryptography is a specialized field; use peer-reviewed, industry-standard libraries.

2. Use High-Entropy Salts

A salt ensures that two users with the same password ("Password123") have different hashes in the database. This renders rainbow tables useless. Always use a cryptographically secure random salt (which bcrypt and Argon2 do by default).

3. Implement Rate Limiting

Even the slowest hash can be brute-forced if an attacker can make 10,000 requests per second. Implement account lockout policies or exponentially increasing delays (throttling) after failed login attempts.

4. Enforce Password Complexity

While "complex" passwords (symbols, numbers) are less important than "long" passwords (passphrases), enforcing a minimum length (e.g., 12+ characters) significantly increases the time required for a successful crack.

5. Use HTTPS

Hashing protects the password at rest in your database. However, if you aren't using TLS/SSL (HTTPS), the password travels in plain text from the user's browser to your server, where it can be intercepted by a "Man-in-the-Middle" attack.

Comments

Questions, corrections, and tips stay visible for everyone reading this page.

0 in thread

Join the discussion

Shown next to your comment.

Up to 4,000 characters

No comments yet

Be the first to leave a note — it helps the next reader.