Password Hashing: A Security Guide for Developers
Password Hashing: A Security Guide for Developers
Storing passwords correctly is one of the most critical security responsibilities. Get it wrong and a data breach exposes every user's credentials.
Never Store Plaintext
This should go without saying, but plaintext passwords in a database are a catastrophic vulnerability. If the database leaks, every account is compromised instantly.
Why Not Just Hash?
Simple hashing (SHA-256 of password) is not enough:
Rainbow tables — precomputed hash → password lookup tables. Common passwords have known hashes. Speed — SHA-256 can compute billions of hashes per second on a GPU. An attacker can brute-force short passwords quickly.The Right Approach: Password Hashing Functions
Purpose-built algorithms that are deliberately slow and use per-password salts.
bcrypt
The classic choice. Uses a cost factor to control slowness:
$2b$12$LJ3m4ys3Lk0TdkGsZ.kPiOqGlWuKey2deANMxfvCK5mHPiVlyHHGy
│ │ └── 22-char salt + 31-char hash
│ └── cost factor (2^12 = 4096 iterations)
└── algorithm version
Argon2
The modern winner (Password Hashing Competition 2015). Configurable memory usage defeats GPU attacks:
Argon2id — recommended variant (resists both side-channel and GPU attacks)
Parameters: memory=65536 KB, iterations=3, parallelism=4
PBKDF2
Widely supported (built into Web Crypto API). Uses iteration count for slowness:
const key = await crypto.subtle.deriveBits(
{ name: "PBKDF2", salt, iterations: 600000, hash: "SHA-256" },
baseKey,
256
);
Recommended Parameters (2026)
| Algorithm | Minimum | Recommended |
|-----------|---------|-------------|
| bcrypt | cost=10 | cost=12 |
| Argon2id | 64MB, 3 iter | 64MB, 4 iter |
| PBKDF2-SHA256 | 600,000 iter | 1,000,000 iter |
Salt
A random value prepended to each password before hashing. Ensures identical passwords produce different hashes. bcrypt and Argon2 handle salting automatically.
Pepper
A secret key added to all passwords before hashing, stored separately from the database (e.g., in an environment variable). Adds defense-in-depth — even with a full DB dump, the attacker needs the pepper too.
Try It
Use our Password Hasher tool to hash and verify passwords with configurable cost parameters, entirely in your browser.
Conclusion
Use bcrypt (cost=12) or Argon2id. Never roll your own hashing. Always salt. Consider peppering. Increase cost factors over time as hardware gets faster.