How to Store Passwords Safely (Hashing Guide)
Password hashing is the single most important thing to get right when you store user credentials, and getting it wrong is the most damaging beginner mistake in authentication. This guide explains why you hash instead of encrypt, why salting is non-negotiable, and which algorithms to reach for in 2026. If your app stores passwords, this is the page to read before your next release.
Never store passwords in plain text
The first rule of password hashing is that you never keep the password itself. Plain-text storage means the day your database leaks—through a backup, a query log, or an injection bug—every account is compromised instantly. Because people reuse passwords, their accounts on other services are exposed too.
Hashing solves this by storing a one-way fingerprint of the password instead of the password. When a user logs in, you hash what they typed and compare it to the stored fingerprint; a match means the password was right, and you never needed the original. If the store leaks, attackers get fingerprints rather than passwords—provided you hashed them properly.
Hashing vs encryption
These two get confused constantly, and the difference matters. Encryption is reversible by design: with the key, ciphertext turns back into the original. Hashing is one-way—there is no key and no un-hash function.
For passwords you want one-way, because you have no legitimate reason to recover the original; you only need to check it. Encryption would mean a key exists somewhere, and whoever steals that key steals every password at once.
| Property | Encryption | Password hashing |
|---|---|---|
| Reversible? | Yes, with the key | No, by design |
| Needs a secret key? | Yes | No (uses a salt, not a key) |
| Right for storing passwords? | No | Yes |
Why fast hashes are bad here
Not every hash is suitable. General-purpose hashes like MD5, SHA-1, and SHA-256 are built to be fast, which is exactly what you do not want for passwords. Speed helps an attacker who has your leaked hashes guess billions of candidates per second on commodity hardware.
Password hashing uses deliberately slow, resource-heavy algorithms so each guess costs real time and memory. The goal is not to make hashing instant but to make mass guessing impractical. A hash that takes a fraction of a second for one login is fine for you and painful for anyone trying to crack millions.
Salting and why it matters
A salt is a unique random value added to each password before hashing, then stored alongside the resulting hash. Its job is to make identical passwords produce different hashes, which defeats two attacks at once: precomputed rainbow tables, and the ability to notice that two users share a password.
Salting is not optional, and it is not a secret—it is fine to store the salt next to the hash. The good news is that modern password-hashing libraries generate and store a per-password salt for you automatically, so you rarely touch it by hand. Just make sure the salt is unique per password, never one global value.
bcrypt, scrypt, argon2
Three algorithms are worth knowing, and any of them is a solid choice in 2026. The current recommendation for new systems is argon2id, but a correctly configured bcrypt remains perfectly acceptable.
| Algorithm | Strength | Notes |
|---|---|---|
| argon2id | Memory-hard; current first choice | Tune memory, iterations, and parallelism |
| scrypt | Memory-hard | Good where argon2 is unavailable |
| bcrypt | Battle-tested, CPU-bound | Handles roughly 72 bytes; still fine when tuned |
Whatever you pick, use a well-maintained library—do not implement these yourself. Avoid plain PBKDF2 unless a compliance rule forces it, and never fall back to a bare general-purpose hash.
Peppering and work factors
The work factor (also called cost) controls how slow the hash is—more iterations or memory means more resistance to cracking. Set it as high as your servers tolerate at real login volume; a common target is a fraction of a second per hash. Revisit it every year or two, because hardware keeps getting faster.
A pepper is an extra secret added to every password but, unlike a salt, kept outside the database—in a secrets manager or hardware module. If your database leaks and the pepper does not, the stolen hashes are much harder to crack. Peppering is a useful extra layer, not a replacement for a strong algorithm and a per-password salt.
Migrating an old password store
If you inherit weak hashes—say unsalted MD5—you do not have to wait for every user to reset. The safe pattern is to upgrade on the fly:
- Wrap the old hashes: store a new strong hash of the existing hash, and record which scheme each row uses.
- On each successful login you briefly have the plain-text password in memory—re-hash it with the new algorithm and replace the stored value.
- Active accounts migrate themselves over time; force a reset for the stragglers after a deadline.
This closes the exposure quickly without a mass password reset, and it lets you retire the weak scheme on a schedule rather than in an emergency.
Frequently asked questions
Which password hashing algorithm should I use in 2026?
Argon2id is the current first choice for new systems, with scrypt and a well-tuned bcrypt as solid alternatives. What matters most is using a slow, salted, purpose-built algorithm from a maintained library—not which of the three you pick. Avoid fast hashes like SHA-256 entirely.
Why can’t I just encrypt passwords instead of hashing them?
Because encryption is reversible: it requires a key, and anyone who steals that key can decrypt every password at once. Hashing is one-way, so a leak exposes only fingerprints. You never need to recover a password—only to verify it—so hashing is the right tool.
Do I need to write my own salting code?
No, and you should not. Modern password-hashing libraries generate a unique random salt per password and embed it in the stored hash automatically. Rolling your own salting is how subtle bugs creep in, so let the library handle it.
Is bcrypt still safe, or is it outdated?
Bcrypt is still safe when configured with an appropriate cost factor. Argon2id is generally preferred for new projects because it is memory-hard, but there is no urgent need to rip out a correctly tuned bcrypt. Keep the work factor current as hardware improves.
Password hashing is not glamorous, but it is the difference between a database leak being an incident and being a catastrophe. Use a slow, salted, well-reviewed algorithm, tune the work factor, and lean on a library rather than your own code. Once storage is solid, look at how those credentials become sessions and tokens—and for the big picture, start with our cornerstone guide.
Last updated: July 6, 2026

Comments
Post a Comment