Two Completely Different Families of Hash
"Hash algorithm" is an umbrella term that covers two families of function with opposite design goals. Cryptographic hash functions like MD5, SHA-1, SHA-256, and SHA-3 are built to be as fast as possible while still being collision-resistant โ they exist to verify integrity, generate checksums, and underpin signatures and HMACs. Password-hashing functions like bcrypt, scrypt, and Argon2 are built to be deliberately slow and memory-hungry, because their entire job is to make guessing a secret expensive for an attacker.
Mixing these up โ using a fast general-purpose hash to protect a password database โ is one of the most common and most damaging security mistakes in application development. It's the root cause behind a large share of "we got breached, here's what was exposed" disclosures over the last two decades.
Fast Hashes: MD5, SHA-1, SHA-256, SHA-3
These algorithms take an input of any size and produce a fixed-length digest. They're deterministic (same input always produces the same output) and designed to run at gigabytes per second on commodity hardware.
- MD5 (128-bit): Cryptographically broken since 2004 โ collisions can be generated deliberately. Still acceptable for non-security checksums (verifying a download wasn't corrupted by chance), but never for anything where an adversary controls the input.
- SHA-1 (160-bit): Deprecated for security purposes since Google and CWI demonstrated a practical collision attack (SHAttered, 2017). Browsers and CAs stopped trusting SHA-1 certificates years ago. Avoid for new systems.
- SHA-256 (256-bit): Part of the SHA-2 family, currently considered cryptographically strong with no known practical collision attacks. The default choice for file integrity checks, blockchain hashing, and as the underlying primitive in HMAC-SHA256.
- SHA-3 (variable, e.g. 256-bit): A different internal design (Keccak sponge construction) standardized by NIST in 2015 as a backup in case weaknesses were ever found in SHA-2. It resists length-extension attacks that SHA-256 is theoretically susceptible to in certain protocol designs.
All four of these are unsalted by default and have no concept of a "work factor." Run the same input through SHA-256 a million times and you get the same digest in nanoseconds, every time. That's a feature for checksums and a serious liability for passwords.
Why SHA-256 Alone Is the Wrong Tool for Passwords
Imagine a password database storing SHA-256(password) for every user, with no salt. Three problems compound immediately:
- No salt means identical passwords produce identical hashes. An attacker who breaches the database can precompute a rainbow table โ a lookup table of common passwords mapped to their SHA-256 digests โ once, and instantly reverse every user who chose a common password.
- SHA-256 is fast, which means brute-forcing is fast. A single consumer GPU can compute billions of SHA-256 hashes per second. An 8-character password drawn from a reasonable character set can be exhausted in hours to days on dedicated cracking hardware; a dictionary-based attack against weak passwords takes minutes.
- There's no way to slow attackers down after the fact. If your hardware budget for cracking doubles next year, SHA-256 hashing doesn't get any harder โ the algorithm itself has no adjustable cost.
Adding a per-user salt to SHA-256 fixes the rainbow table problem but does nothing about raw cracking speed. This is why password-specific algorithms exist โ they bake salting in by default and add a tunable cost.
What Salting and Work Factors Actually Do
A salt is random data, unique per password, that gets mixed in before hashing and stored alongside the result (it doesn't need to be secret). Its only job is to guarantee that two users with the password "correcthorsebattery" end up with two completely different hashes, eliminating precomputed lookup tables and forcing attackers to crack each hash individually.
A work factor (also called a cost factor, or iteration count) controls how many internal rounds of computation the algorithm runs. bcrypt's cost parameter is exponential โ going from cost 10 to cost 11 doubles the time required per guess. Argon2 exposes separate time and memory parameters. The point is that as attacker hardware gets faster over the years, you can simply raise the work factor on new password hashes to keep cracking time roughly constant, without changing the algorithm.
DevOpsArsenal Hash Generator
Generate MD5, SHA-1, SHA-256, and SHA-512 digests instantly in your browser using the Web Crypto API โ useful for checksums, integrity verification, and learning how each algorithm behaves on real input.
Try Hash Generator Free โSlow Hashes: bcrypt, scrypt, Argon2
These three algorithms were purpose-built for password storage and all share the same core idea: be slow, be tunable, and resist hardware acceleration.
- bcrypt (1999): Based on the Blowfish cipher, with a built-in salt and an adjustable cost factor (commonly 10โ12 in 2026). Battle-tested for over two decades and still a solid default. Its main limitation is a 72-byte input cap and relatively low memory usage, which makes it somewhat more GPU-parallelizable than scrypt or Argon2.
- scrypt (2009): Designed to be "memory-hard" โ it deliberately requires large amounts of RAM per hash attempt, which makes building cheap parallel cracking hardware (ASICs, GPU farms) much harder than it is for bcrypt.
- Argon2 (2015): Winner of the Password Hashing Competition and the current recommendation from OWASP. Argon2id (the hybrid variant) tunes memory cost, time cost, and parallelism independently, giving the strongest resistance to both GPU and side-channel attacks of the three.
If you're building something new in 2026, OWASP's guidance is to use Argon2id where the library ecosystem supports it well, with bcrypt as the well-understood fallback when it doesn't.
Decision Table: Which Algorithm for Which Job
| Use Case | Right Tool | Why |
|---|---|---|
| File integrity / checksum | SHA-256 | Speed is desirable; no secret involved, just detecting accidental corruption. |
| HMAC signing (API auth, webhooks) | HMAC-SHA256 | Combines a shared secret key with a fast hash for authenticated, tamper-evident messages. |
| Password storage | Argon2id or bcrypt | Deliberately slow, salted, tunable work factor resists brute-force at scale. |
| Content-based deduplication | SHA-256 or SHA-1 | Speed matters for hashing large volumes of files; collision resistance, not secrecy, is the goal. |
| Digital signatures / TLS certificates | SHA-256 / SHA-3 | Required by current standards (SHA-1 is rejected by modern browsers and CAs). |
| API key / session token generation | crypto.getRandomValues() + hash for storage | Tokens should be random, not derived from anything guessable; hash only the stored copy. |