Hashing is one of the most misunderstood topics in practical software security. The word "hashing" covers two completely different jobs: verifying that data hasn't changed (integrity), and safely storing passwords so a database breach doesn't expose user credentials. The algorithms suited to these two jobs work in fundamentally different ways, and using the wrong one in the wrong context has caused some of the most damaging breaches in recent history.
Overview
A cryptographic hash function takes an arbitrary-length input and produces a fixed-length output, the digest. The function runs one-way: given the digest, you can't recover the original input without brute-force. It's deterministic, so the same input always produces the same output. And it shows the avalanche effect, where a single-bit change in input produces a completely different output.
MD5, SHA-256, and bcrypt are all hash functions, built for different jobs.
MD5 (1991) was designed for speed and is now cryptographically broken. Output: 128 bits. SHA-256 (2001, NIST) was designed for integrity and signatures, secure but too fast for passwords. Output: 256 bits. bcrypt (1999) was designed specifically for passwords, intentionally slow and self-salting. Output: a 60-character encoded string.
Generate hashes with the Hash Generator to see the output format for each algorithm.
Side-by-Side Comparison
| Parameter | MD5 | SHA-256 | bcrypt |
|---|---|---|---|
| Output length | 128 bits (32 hex characters) | 256 bits (64 hex characters) | 60-character encoded string (includes salt + cost) |
| Speed | Extremely fast (~10 billion hashes/sec on GPU) | Fast (~1 billion hashes/sec on GPU) | Intentionally slow (~10,000 hashes/sec at cost 12) |
| Collision resistance | Broken, collisions demonstrated since 2004 | Strong, no known collisions | Not applicable (non-deterministic; designed for uniqueness) |
| Salting | No built-in (must be added manually) | No built-in (must be added manually) | Built-in, random 128-bit salt per hash |
| Reversible | No, but GPU brute-force and rainbow tables make it trivial | No, computationally infeasible for strong passwords | No, slow per-attempt cost defeats GPU attacks |
| Use for passwords | Never | Never | Yes, recommended minimum |
| Use for data integrity | Avoid (collision risk) | Yes, standard choice | No, non-deterministic, not suitable |
MD5: Deep Dive
MD5 was designed by Ron Rivest in 1991 and dominated checksum and password hashing through the 2000s. It produces a 128-bit digest in nanoseconds, so fast that a single modern GPU (Nvidia RTX 4090) can compute approximately 164 billion MD5 hashes per second.
Collision attacks, finding two different inputs that produce the same MD5 output, were demonstrated by researchers in 2004 and fully automated by 2005. By 2008, researchers had created a rogue SSL certificate by exploiting MD5 collisions in certificate authorities, and the attack ran on ordinary consumer hardware. MD5 now sits on the explicit "do not use" list in every major security standard, including NIST SP 800-131A, PCI DSS, and OWASP.
Password cracking makes the case even without collision attacks. An attacker who obtains an MD5 password hash can test every entry in the RockYou wordlist, 14 million passwords, in under 1 millisecond. Add rules and variations, and billions of candidates become testable per second. The 2012 LinkedIn breach exposed 6.5 million unsalted SHA-1 hashes; a similar breach with MD5 would crack within seconds.
MD5 still shows up in a few places. Checksums get published alongside software downloads to catch transmission errors, and in a non-adversarial context, where you own both the file and the checksum and the only threat is accidental corruption, MD5 works fine. It also handles non-cryptographic jobs: generating cache keys, deduplicating files in private storage, hash maps where collision resistance isn't a security requirement. For any of these, SHA-256 runs just as fast from a user's perspective and closes off the security question entirely.
The verdict on MD5 is straightforward: keep it out of any security context. Replace legacy MD5 password hashes right away. A common migration approach is re-hashing the existing MD5 hash with bcrypt on first login and storing the new hash going forward.
SHA-256: Deep Dive
SHA-256 belongs to the SHA-2 family, standardised by NIST in 2001. It produces a 256-bit digest (64 hex characters) with no known collisions, and it underpins nearly every security-critical system in modern infrastructure: TLS certificate fingerprinting, code signing, digital signatures, HMAC authentication, blockchain proof-of-work.
SHA-256 fits jobs built around integrity and authentication, verifying that data hasn't been altered. It's deterministic, collision resistant, and fast enough to process large files or high-frequency network traffic without becoming a bottleneck. A few practical uses:
- File integrity.
sha256sum file.tar.gzon Linux produces a digest you can publish alongside a download, and downloaders verify the computed digest against the published one. - Digital signatures. TLS 1.3 mandates SHA-256 for certificate signatures. Your browser's HTTPS padlock depends on SHA-256 to verify the server certificate hasn't been forged.
- HMAC-SHA256. The standard for API request signing (AWS Signature Version 4, GitHub webhook signatures, Stripe webhook verification). The HMAC construction uses a secret key so an attacker without the key can't forge a valid MAC.
- Blockchain. Bitcoin's proof-of-work and transaction IDs use double-SHA-256. Ethereum uses Keccak-256.
Speed is SHA-256's strength for data integrity, and its fatal weakness for passwords. A modern GPU computes approximately 1 billion SHA-256 hashes per second. Get hold of a SHA-256 password hash and an attacker can test every entry in common wordlists, every 8-character alphanumeric combination, and every known password pattern from previous breaches within minutes to hours. A random salt stored alongside the hash defeats rainbow tables, but does nothing to slow per-hash computation speed. The attacker still tests 1 billion candidates per second per GPU.
SHA-512 produces a longer 512-bit digest and runs faster than SHA-256 on 64-bit CPUs, since the algorithm operates on 64-bit words internally. SHA-256's 128-bit security level covers all current applications just fine. Stick with SHA-256 for compatibility, and reach for SHA-512 only when a longer output is explicitly needed, key derivation contexts being the main example.
bcrypt: Deep Dive
Niels Provos and David Mazières designed bcrypt in 1999 specifically for password hashing, built around one core insight: password hashing should be slow, tunably slow, so brute-force stays expensive even as hardware improves.
bcrypt's work factor (cost) is an integer controlling the number of iterations, and the algorithm performs 2^cost key schedule rounds. At cost 10, hashing takes approximately 100ms on a modern server. At cost 12, approximately 250ms. At cost 14, approximately 1 second. An attacker testing 1 billion passwords per second against MD5 can manage only about 4,000 passwords per second against bcrypt at cost 12 on the same hardware. You can raise the cost factor over time as hardware improves; OWASP recommends re-evaluating every two years.
bcrypt generates a cryptographically random 128-bit salt for every hash and embeds it in the output string. That 60-character output encodes the algorithm version, cost factor, salt, and hash in a single self-contained string. During verification, the function pulls the salt and cost from the stored string and re-hashes the candidate, so no separate storage is needed. Two identical passwords hashed with bcrypt produce different outputs, which makes rainbow tables completely useless against it.
There's a catch though: bcrypt processes only the first 72 bytes of input, and anything beyond gets silently discarded. Most real-world passwords never hit this limit (the median password runs under 20 characters). For systems that explicitly encourage long passphrases, the standard fix is pre-hashing the password with SHA-256, producing a 32-byte value, before passing it to bcrypt. Take care here: some bcrypt implementations treat a null byte in the pre-hashed output as a string terminator, so use the hex or base64 representation of the SHA-256 digest rather than raw bytes.
Argon2id won the Password Hashing Competition in 2015 and stands as OWASP's first recommendation for new systems as of 2026. It adds a configurable memory cost parameter, requiring a minimum amount of RAM per hash, which resists GPU attacks that parallelise thousands of low-memory bcrypt computations. OWASP's current minimum configuration for Argon2id runs memory 19 MiB, iterations 2, parallelism 1. Implement Argon2id for new systems. For existing systems already on bcrypt at cost 12 or higher, migration isn't urgent since bcrypt remains secure in practice.
bcrypt shows up everywhere in production. PHP's password_hash() defaults to it. Node.js's bcrypt and bcryptjs libraries see wide use. Spring Security defaults to bcrypt at cost 10. PostgreSQL's pgcrypto extension includes it too. If your framework ships a password hashing helper, use it. Framework defaults are usually correct and save you from implementation errors.
When to Use MD5
Honestly, rarely, and never for security. A few acceptable non-security uses in 2026: generating cache keys where collision probability doesn't matter, deduplicating files in a private, non-adversarial system, or maintaining legacy compatibility when you can't change what the counterparty sends or stores.
In every case, ask whether SHA-256 would work instead. It runs just as fast from a human perspective, carries no known weaknesses, and removes any future security question. The only real reason to pick MD5 is when an external system forces your hand.
When to Use SHA-256
SHA-256 fits well for file integrity verification (checksums published alongside downloads), digital signatures and certificate fingerprinting (TLS, code signing, S/MIME), HMAC message authentication (API signing, webhook verification, cookie integrity), blockchain and distributed ledger applications, key derivation (feeding into HKDF or PBKDF2, not standalone for passwords), and content-addressable storage (Git used SHA-1 historically, newer formats migrate to SHA-256).
Don't use raw SHA-256 for passwords even with a salt attached. The speed that makes it excellent for data integrity makes it dangerous for password storage.
When to Use bcrypt
bcrypt, or Argon2id for new implementations, is the appropriate choice for storing user passwords in any application, for any secret a user supplies at login that needs later verification, and for API key storage when you need to verify the key without storing it in plaintext.
Use a cost factor of at least 12 on server hardware in 2026, and benchmark on your actual production hardware. A cost factor that takes 250ms on a dedicated server might take 2 seconds on a shared virtual machine with limited CPU allocation.
Our Verdict
The rules here are simple. For passwords, use bcrypt at cost 12 or higher, or Argon2id for new systems. Never MD5. Never raw SHA-256. The history of credential breaches, LinkedIn, RockYou, Adobe, Yahoo, is largely a history of password databases hashed with fast algorithms. Don't add your application to that list.
For data integrity, signatures, and MACs, use SHA-256. It carries no known weaknesses, has universal support, and stands as the standard for TLS, code signing, HMAC, and blockchain. Reach for HMAC-SHA256 specifically when authentication, not just integrity, is needed.
For MD5, the only legitimate reason left is legacy compatibility or non-adversarial deduplication. If you get to choose, choose SHA-256 instead.
The Hash Generator lets you compute MD5, SHA-256, SHA-512, and other digests instantly to understand output formats and test implementations.