Guide

How Passwords Are Hashed — bcrypt, SHA-256, and Why It Matters

Storing plaintext passwords is a critical security failure. Learn how password hashing works, why SHA-256 alone is not enough, what salting does, and why bcrypt, scrypt, and Argon2 are the right tools for password storage.

Why you never store a plaintext password

If your database is breached, every user whose password was stored in plaintext is immediately compromised — and because people reuse passwords, their other accounts are too. This is not a theoretical risk; it has happened to LinkedIn, Adobe, RockYou, and hundreds of others.

The solution is to store a hash of the password, not the password itself. When the user logs in, you hash what they typed and compare it to the stored hash. You never need to see the original password again.

Why SHA-256 alone is not enough

SHA-256 is an excellent general-purpose hash function — but it was designed to be fast. A modern GPU can compute billions of SHA-256 hashes per second. That is a problem for passwords.

An attacker with a leaked database of SHA-256-hashed passwords can run a brute-force attack trying every common word, name, and variation at billions of guesses per second. Most 8-character passwords fall within minutes.

⚠ Never use MD5 or SHA-256 directly to hash passwords. Use a purpose-built slow hash function instead.

What is salting?

A salt is a random value generated uniquely for each user and appended to their password before hashing. The salt is stored alongside the hash in plaintext — it does not need to be secret.

Without salt — two users with the same password get the same hash:
password123ef92b... ← identical for every user
With salt — same password, different hashes:
password123 + salt a7f39c4d2...
password123 + salt k2m93b81a...

Salting defeats rainbow table attacks (precomputed hash lookup tables) because the attacker would need a separate rainbow table for every possible salt value — computationally infeasible.

Purpose-built password hashing algorithms

These algorithms are deliberately slow and memory-intensive, making brute-force attacks expensive even with specialist hardware.

AlgorithmDesignedTunable cost?Memory-hard?Recommendation
bcrypt1999✓ Work factor✗ NoGood — widely supported
scrypt2009✓ N, r, p✓ YesGood — stronger than bcrypt
Argon2id2015✓ Time + memory✓ YesBest — winner of Password Hashing Competition
PBKDF22000✓ Iterations✗ NoAcceptable — used in FIPS environments

How bcrypt works

bcrypt automatically generates a random 128-bit salt and embeds it in the output hash string. The work factor (cost parameter, typically 10–14) controls how many iterations are performed — doubling it doubles the time required.

bcrypt hash output format:
$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewkMgGg9a4nSTM
$2b$ = version · $12$ = cost factor · next 22 chars = salt · rest = hash

Quick reference: what to use

  • Storing user passwords — Argon2id (first choice), bcrypt (widely supported fallback)
  • File integrity / checksums — SHA-256
  • API token signing (HMAC) — SHA-256 via HMAC
  • Digital signatures — SHA-256
  • Anything security-critical — never MD5, never SHA-1, never raw SHA-256 for passwords

Related guides

Generate SHA-256, SHA-512, MD5, and SHA-1 hashes

Useful for checksums, verifying data integrity, and learning

Open SHA-256 Generator →
How Passwords Are Hashed — bcrypt, SHA-256, and Why It Matters | DataToolkit | DataToolkit