Password Hashing: Definition, How It Works, and Where You’ll See It
Password hashing is the process of transforming a plaintext password into a fixed-format, one-way value (“hash”) for storage and verification. Done correctly, it ensures that even if a password database is stolen, attackers must still perform expensive guessing (offline cracking) to recover passwords.
Password hashing is the standard way modern systems store passwords safely: instead of saving the plaintext password, they store a one-way value derived from it. Good password hashing (with a unique salt and a slow KDF like Argon2id or bcrypt) is one of the biggest factors that determines whether a database leak becomes a minor incident or a full-scale account takeover via offline cracking.
How password hashing works
Password hashing is not about encrypting the password and decrypting it later. It’s about storing a value that allows verification without storing the secret itself.
At a high level:
- User chooses a password (e.g.,
CorrectHorseBatteryStaple). - The system generates a unique random salt for that account.
- The system runs a password hashing algorithm / KDF (key derivation function) using the password + salt and a work factor (cost).
- The system stores the output (often along with the salt and parameters).
- At login, the system recomputes the hash using the provided password and compares it to the stored value.
Why salts matter
A salt is non-secret random data added to the password before hashing (or incorporated into the KDF). Unique salts:
- Prevent attackers from using precomputed tables (e.g., rainbow tables).
- Ensure that two users with the same password do not end up with the same stored hash.
- Force attackers to attack each password independently, increasing total cracking cost.
Why “slow” matters (work factors and memory hardness)
General-purpose hash functions like MD5 or SHA-1/SHA-256 are designed to be fast, which is great for integrity checks but bad for password storage. If an attacker steals a hash database, fast hashes allow billions of guesses per second on GPUs.
Password hashing algorithms intentionally make guessing expensive by requiring:
- Many iterations (CPU cost), e.g., bcrypt’s cost factor
- High memory usage (memory-hardness), e.g., Argon2 and scrypt
The goal is to slow down each guess so that an offline cracking attack becomes impractical at scale—especially for weak, common passwords.
What gets stored in the database
In most real implementations, the stored “hash” field is not just raw bytes. It’s commonly an encoded string containing:
- Algorithm identifier (e.g.,
$2b$for bcrypt,$argon2id$for Argon2id) - Parameters (cost/iterations/memory/parallelism)
- Salt
- Derived key (hash output)
This is intentional: it allows you to upgrade parameters over time and still verify old hashes.
Recommended algorithms (practitioner view)
For modern systems, the practical choices are:
- Argon2id (generally preferred when available; strong defense with memory hardness)
- bcrypt (widely supported; still acceptable with appropriate cost)
- scrypt (also memory-hard; good choice where Argon2 isn’t available)
Avoid for password storage:
- MD5, SHA-1
- “Just SHA-256(password)” (even with a salt, it’s typically too fast without stretching/KDF)
- Custom constructions
Example formats you’ll see
# bcrypt (format varies by implementation)
$2b$12$wq9o8OqZkE1o1QkTQvO7aO5s8x3qG1r1f7g1lq2dK4aY0mPpPzD3K
# Argon2id
$argon2id$v=19$m=65536,t=3,p=2$c29tZXNhbHQ$ZGVyaXZlZGtleWJ5dGVz...
These strings embed parameters; you can often tune them without schema changes.
Hashing and verification (conceptual pseudocode)
# registration
salt = random_bytes(16)
hash = KDF(password, salt, params)
store(user, salt, params, hash)
# login
salt, params, stored_hash = load(user)
candidate = KDF(input_password, salt, params)
if constant_time_compare(candidate, stored_hash):
allow_login()
else:
deny()
Key details practitioners care about: - Use constant-time comparison to reduce timing side-channel risk. - Don’t reuse salts. - Store parameters per-hash to enable incremental hardening.
Parameter tuning mindset
There is no single “perfect” cost setting. Tune so that hashing takes a noticeable time on your production hardware (often tens to a few hundreds of milliseconds per hash) without breaking user experience or authentication throughput. Reassess periodically and after hardware changes.
Where you’ll encounter password hashing
You’ll run into password hashing anywhere passwords are stored or validated—even when users never see it.
Web applications and SaaS backends
Most web apps store password hashes in a user table. If you administer an app:
- Confirm the app uses a modern password hashing algorithm (Argon2id/bcrypt/scrypt).
- Confirm salts are unique per user.
- Ensure password resets invalidate sessions/tokens appropriately (hashing doesn’t fix session hygiene).
What to look for in database dumps/logs
If you ever see leaked records (e.g., in an incident response context), hash identifiers give quick clues:
"$2a$","$2b$","$2y$"→ bcrypt variants"$argon2id$"→ Argon2id"$scrypt$"or library-specific prefixes → scrypt- 32 hex characters (e.g.,
5f4dcc3b...) → often MD5 (red flag) - 40 hex characters → often SHA-1 (red flag)
- 64 hex characters → often SHA-256 (needs scrutiny; may still be too fast)
Identity providers (IdP) and directories
In centralized authentication systems (on-prem directories or cloud IdPs), password hashing and verification are core functions. You may not control the hashing algorithm, but you still influence risk via:
- MFA enforcement
- Password policy (length, banned passwords)
- Detection of password spraying and credential stuffing
- Secure sync/replication configurations (where applicable)
If you’re rolling out stronger login controls alongside hashing improvements, see: What is Multi-Factor Authentication (MFA)?
Operating systems and device authentication
Local OS account databases store password verifiers (hashes). As an admin, you’ll encounter:
- Credential dumping concerns on compromised hosts
- The need for full-disk encryption and least privilege to reduce attacker access to stored verifiers
- Offline attack risk when attackers get copies of credential stores
Incident response and breach impact analysis
Password hashing quality determines how quickly stolen credentials turn into real account takeovers:
- Strong hashing buys time and reduces recovered password volume.
- Weak hashing (fast hashes, no salt) often leads to rapid mass compromise, especially where users reuse passwords.
If you’re communicating user risk after suspicious activity, pair hashing insights with account-level indicators and checks: FAQ: How do I tell if my email has been hacked?
Practical hardening checklist (quick)
- Use Argon2id when available; otherwise bcrypt or scrypt.
- Ensure unique per-user salts (generated securely).
- Store algorithm + parameters with the hash so you can upgrade over time.
- Add a pepper if you can protect it properly (secrets manager/HSM).
- Monitor and rate-limit login attempts; enable MFA for high-risk accounts.
- Prefer a reputable password manager to reduce reuse and increase password length (for example, 1Password: Try 1Password →).
For end-user protection on untrusted networks, a VPN can reduce exposure to some local-network threats (though it doesn’t “fix” weak passwords or poor hashing). If a VPN fits your threat model, consider NordVPN: Check NordVPN pricing → or Surfshark: Try Proton VPN →. For malware and credential-stealer defense on endpoints, consider Malwarebytes: Get Malwarebytes →.
This article may contain affiliate links. We earn a commission on qualifying purchases at no extra cost to you.
Related terms
A one-way function producing fixed-size output. For passwords, you typically want a specialized KDF rather than a fast general hash.
A function that derives a key from input material using cost parameters. Password hashing algorithms are specialized KDFs.
Unique random value stored with the hash to prevent precomputation and duplicate-hash matching.
A secret value (like an application-wide key) mixed into password hashing, stored separately from the database (e.g., in an HSM or secrets manager). Helps if the DB leaks but the app secret does not.
Settings that control hashing difficulty (iterations, CPU cost, memory cost). Higher cost slows attackers and your own login system.
Increasing the computational effort required to test each password guess (often via iterations or KDF parameters).
Attacker guesses passwords against stolen hashes without interacting with your live systems. This is the main threat password hashing is designed to slow down.
Precomputed hash lookups for common passwords. Salts largely defeat these.
Using passwords stolen from one site to log into others. Strong hashing reduces how many passwords get recovered after a breach, but MFA and detection are still critical.
Comparison method designed to avoid leaking information via timing differences during hash verification.