Hashing explained: MD5, SHA-1, SHA-256 and what broken means
What hash functions do, why MD5 and SHA-1 are broken, checksums vs password hashing, and hex vs base64 digests.
Published 2026-09-25
What a hash function actually does
A cryptographic hash function takes input of any length and produces a fixed-length output — the digest — deterministically: the same input always produces the same digest, a one-bit change in the input produces a completely different digest, and there's no practical way to go from the digest back to the input. MD5 produces a 128-bit digest, SHA-1 a 160-bit digest, SHA-256 a 256-bit digest, SHA-512 a 512-bit digest — the number in the name is the digest size in bits.
Hashing is not encoding and not encryption. Encoding (like Base64) is reversible and keyless. Encryption is reversible with the right key. Hashing is one-way by design — there is no key that turns a digest back into the original input, and a well-designed hash function makes that direction computationally infeasible even to try.
sha256("hello world") = b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
Change one character and the output is unrecognizable:
sha256("Hello world") = 64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c
Two different kinds of "broken"
"Broken" gets used loosely, but it means one of two specific things, and they matter differently depending on what you're using the hash for:
- Collision resistance: how hard is it to find any two different inputs that produce the same digest? Neither input is chosen in advance — an attacker just needs some colliding pair.
- Preimage resistance: how hard is it, given a digest, to find any input that produces it? This is the "reverse the hash" attack, and it's a much harder problem than finding a collision — for an n-bit hash, collision resistance tops out around 2^(n/2) work (the birthday bound) while preimage resistance stays near the full 2^n. For SHA-256 that's roughly 128-bit collision strength against a 256-bit preimage strength, per NIST's hash function guidance.
MD5 and SHA-1 are broken specifically on collision resistance — attackers can construct two different inputs that hash identically, which is enough to break anything relying on "this hash uniquely identifies this content" (code-signing certificates, document integrity).
MD5: broken since 2004
MD5 produces a 128-bit digest. In August 2004, Xiaoyun Wang and colleagues published practical collisions for full MD5, findable in about an hour on the hardware of the time. The attack was refined into chosen-prefix collisions — an attacker can make two documents with different, attacker-chosen prefixes collide, which is exactly what's needed to forge two different-looking files (say, a safe PDF and a malicious one) with the same MD5. This isn't theoretical: in 2012, the Flame malware used an MD5 collision to forge a Windows code-signing certificate. MD5 has been considered "cryptographically broken and unsuitable for further use" since 2008. It still shows up for non-security purposes — deduplication keys, cache-busting hashes, quick data fingerprints — where nobody is trying to deliberately construct a collision.
SHA-1: broken since 2017
SHA-1 produces a 160-bit digest and was NIST's recommended hash after MD5's collapse. NIST deprecated it for digital signatures in 2011 and disallowed that use entirely by the end of 2013, based on theoretical weaknesses. Those weaknesses became practical in February 2017, when researchers from Google and CWI Amsterdam published SHAttered, the first real SHA-1 collision: two different PDFs with an identical SHA-1 digest, found in about 2^63.1 operations — roughly 100,000 times faster than brute force. Every major browser stopped accepting SHA-1 TLS certificates that same year. NIST's stated plan is to phase SHA-1 out of remaining federal use by 2030; for anything you control today, there's no reason to reach for it over SHA-256.
SHA-256 and SHA-512: still solid
SHA-256 and SHA-512 (the SHA-2 family, defined in FIPS 180-4) remain NIST-approved with no known practical attack on either collision or preimage resistance. SHA-3, a structurally different design standardized later as a hedge against future SHA-2 attacks, is also approved. For anything that needs a general-purpose cryptographic hash today — integrity checks, digital signatures, content addressing — SHA-256 is the reasonable default, with SHA-512 an option where the larger digest or its performance profile on 64-bit hardware helps.
Checksums: a different job entirely
Not every hash-shaped tool is a cryptographic hash. CRC32 is a checksum, not a cryptographic hash function — it's built to catch accidental corruption cheaply, which is exactly what gzip uses it for: detecting bit flips from a bad disk or a truncated transfer. CRC32 has no collision resistance against a deliberate attacker — constructing two different inputs with the same CRC32 is trivial by design, since it's optimized for speed and error-detection coverage, not for resisting someone trying to fool it. Use CRC32 (or the CRC32 tool) for "did this file get corrupted in transit," and a cryptographic hash for "can I trust that this content hasn't been deliberately tampered with."
Why you should never hash passwords with SHA-256 directly
This is the mistake that causes real damage. SHA-256 is fast — that's a feature for integrity checks and a serious liability for passwords. Speed is exactly what an attacker wants when brute-forcing a stolen password database: a fast general-purpose hash lets modern GPU hardware attempt billions of guesses per second against every leaked hash at once. OWASP's password storage guidance is explicit that fast hashes like SHA-256 "are not suitable for password storage because they allow attackers to perform large numbers of guesses quickly."
The fix is a password hashing function, not a general-purpose one: Argon2id (OWASP's current first choice), scrypt, bcrypt, or PBKDF2 with a high iteration count. These are deliberately slow (Argon2id and scrypt are also memory-hard), with a tunable work factor you can raise as hardware improves, and they take a per-password salt (good libraries generate and store it for you) so identical passwords don't produce identical hashes. None of that is what a generic hash tool does — for authentication, reach for a password-hashing library, not this hub's hash generator, which is built for file integrity and cache keys, not passwords.
Hex vs base64 digests
A hash digest is just bytes — how you display those bytes is a separate choice. Hex encodes each byte as two characters (0–9, a–f), so a 256-bit SHA-256 digest is 64 hex characters; it's the most common representation because it's unambiguous and easy to eyeball. Base64 packs the same bytes more densely (roughly 4 characters per 3 bytes), so the same 256-bit digest is about 44 base64 characters — shorter, but harder to scan by eye and occasionally in need of URL-safe encoding if it ends up in a URL. Neither is more "correct"; they're two textual representations of identical underlying bytes, and a hash generator that offers both is just letting you pick the format your downstream system expects.
A practical checklist
- Need to check a file wasn't corrupted in transit? CRC32 or any hash works — corruption is accidental, not adversarial.
- Need to prove content wasn't deliberately tampered with? Use SHA-256 or SHA-512, never MD5 or SHA-1.
- Need to store a password? Don't use a hash generator at all — use Argon2id, bcrypt, or PBKDF2 from an authentication library.
- Comparing digests from two different tools and they don't match? Check hex vs base64 encoding before assuming the hash itself is wrong.