MD5 vs SHA-256: Understanding Hash Functions

Security - 3 min read - Published 2026-08-27 - Updated 2026-10-19

A hash function takes any input - a word, a file, a whole disk image - and produces a short, fixed-length fingerprint called a hash or digest. The same input always gives the same hash, and even a tiny change to the input gives a completely different one. Hashes are used to check that downloads aren't corrupted, to detect tampering, to sign software and documents, and as building blocks in almost every security system.

MD5 and SHA-256 are two of the best-known hash functions. They look similar, but they're in very different states: SHA-256 is trusted for security, while MD5 has been broken for twenty years.

What a good hash function guarantees

Three properties matter. It should be one-way: given a hash, there's no practical way to work back to the input. It should be collision-resistant: it should be practically impossible to find two different inputs with the same hash. And it should show the avalanche effect: changing one character changes about half the bits of the output.

You can see the avalanche effect directly. The SHA-256 hash of hello is 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824, while the hash of Hello, with just a capital H, is 185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969. The two share no visible pattern.

MD5: fast, short and broken

MD5 produces a 128-bit hash, written as 32 hexadecimal characters; the MD5 of hello is 5d41402abc4b2a76b9719d911017c592. It was designed in 1991 and was everywhere by the 2000s.

Its collision resistance is gone. Researchers published practical MD5 collisions in 2004, and the attacks have since become fast enough to run on an ordinary computer. In 2012 the Flame malware used an MD5 collision to forge a Microsoft code-signing certificate, which let it pass as legitimate software. Anywhere an attacker could benefit from two different files sharing a hash - certificates, signatures, verifying that a file hasn't been tampered with - MD5 must not be used.

MD5 is still acceptable for non-security jobs: detecting accidental corruption when copying files, deduplicating data you control, or as a quick cache key. Random errors won't produce collisions; only deliberate attacks do.

SHA-256: the current standard

SHA-256 is part of the SHA-2 family, published by the US National Institute of Standards and Technology in 2001. It produces a 256-bit hash, written as 64 hexadecimal characters. No practical collision or pre-image attack is known, and it's used in TLS certificates, software signing, Git (which is moving from SHA-1 to SHA-256), and Bitcoin.

Its older sibling SHA-1 (160 bits) is in a similar position to MD5: a practical collision was demonstrated publicly in 2017, so it shouldn't be used for security either. SHA-3, standardized in 2015, uses a different internal design and is an alternative to SHA-2, but SHA-256 remains the most widely used choice.

Verifying a download

Many software sites publish a SHA-256 checksum next to each download. After downloading, compute the file's hash and compare it with the published value; if they match exactly, the file arrived intact. On Windows, PowerShell's Get-FileHash command does this; on macOS and Linux, shasum -a 256 or sha256sum. A file hash checker in the browser works too, without uploading the file.

A checksum only protects you if the published value itself is trustworthy. If an attacker can change the download, they may be able to change the checksum on the same page. That's why important software is also signed with a cryptographic key, which proves who published it.

Why neither should store passwords

General-purpose hashes are designed to be fast, and that's exactly wrong for passwords. If a database of SHA-256 password hashes leaks, attackers can test billions of guesses per second, and precomputed tables cover common passwords instantly when no salt is used.

Passwords should be stored with a purpose-built password hashing function such as Argon2, scrypt or bcrypt. These are deliberately slow and memory-hungry, include a unique random salt for every password, and let the cost be increased as hardware gets faster. If you're building a login system, use your framework's built-in password hashing rather than calling a hash function yourself.

Related Tools

Related Articles