MD5 vs SHA-1 vs SHA-256: Which Hash Should You Use?

Use SHA-256 for anything security-related; MD5 and SHA-1 are only acceptable where nobody gains anything by forging a matching hash.

MD5, SHA-1 and SHA-256 all do the same job: they turn input of any length into a short, fixed-size fingerprint called a digest. The same input always gives the same digest, and changing a single bit changes the whole result. The three differ in digest length, in speed and, most importantly, in whether someone can deliberately produce two different inputs with the same digest. For MD5 and SHA-1 that has been done in public. For SHA-256 it has not.

The three algorithms at a glance

MD5SHA-1SHA-256
Digest size128 bits, 32 hex characters160 bits, 40 hex characters256 bits, 64 hex characters
Published1992 (RFC 1321)1995 (FIPS 180-1)2001, as part of the SHA-2 family
CollisionsPractical since 2004Practical since 2017No known attack
Finding an input for a given digestNo practical attackNo practical attackNo practical attack
Good for todayNon-security checksums, cache keysLegacy compatibility onlyThe default for new work

Here are the full digests of the five bytes hello, as printed by md5sum, sha1sum and sha256sum. The Hash Generator shows the same values side by side, plus SHA-384 and SHA-512, for text or for a file up to 50 MB.

MD5      5d41402abc4b2a76b9719d911017c592
SHA-1    aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
SHA-256  2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

What the extra bits buy you

Digest length sets the cost of a generic attack, one that treats the function as a black box. Because of the birthday paradox, finding any two colliding inputs takes about 2^(n/2) attempts for an n-bit digest: 2^64 for MD5, 2^80 for SHA-1 and 2^128 for SHA-256. Finding an input that matches one specific digest (a preimage) takes about 2^n.

Those numbers only hold while the design has no shortcut. MD5 and SHA-1 both have shortcuts for collisions, which is why their length no longer tells the whole story. SHA-256 has no known shortcut, and 2^128 is far beyond any computing power that exists.

How MD5 and SHA-1 were broken

A collision attack does not let anyone reverse a hash. It lets an attacker prepare two different inputs in advance that share one digest, then get one of them trusted and swap in the other. The dangerous variant is a chosen-prefix collision, where the attacker picks two meaningful starts, such as two certificates with different names, and computes extra bytes that make the digests equal.

  • MD5, 2004: Xiaoyun Wang and colleagues published practical MD5 collisions.
  • MD5, 2008: a team of researchers used a chosen-prefix MD5 collision to create a rogue certificate authority certificate that browsers would have trusted, because a commercial CA still signed certificates with MD5.
  • MD5, 2012: the Flame malware used an MD5 collision to forge a Microsoft code-signing certificate.
  • SHA-1, 2017: Google and CWI Amsterdam announced SHAttered, two different PDF files with the same SHA-1 digest. The team reported about 6,500 CPU-years and 110 GPU-years of computation.
  • SHA-1, 2020: Gaëtan Leurent and Thomas Peyrin published a practical chosen-prefix SHA-1 collision and used it to impersonate a PGP key.

Browsers stopped accepting SHA-1 TLS certificates in 2017, and NIST announced in December 2022 that SHA-1 should be phased out completely by the end of 2030. Neither MD5 nor SHA-1 has a practical preimage attack: given only a digest, nobody can find an input that produces it. That is why both still work for detecting accidental damage.

Speed: measured, not assumed

MD5 is often described as the fast one. We hashed the same 256 MB of random data with Node 24 (OpenSSL 3.5) on one desktop computer, three runs each:

AlgorithmThroughput on that machine
SHA-1about 1,000 MB/s
MD5about 730 MB/s
SHA-512about 690 MB/s
SHA-256about 460 MB/s

The order depends on the processor. This CPU has no SHA instruction set extensions; processors that do accelerate SHA-1 and SHA-256 in hardware, and SHA-256 can then outrun MD5. SHA-512 beat SHA-256 here because it works on 64-bit words. For short inputs the difference disappears: a million hashes of a short email address took between 1.8 and 2.1 seconds with each of MD5, SHA-1 and SHA-256, because the per-call overhead outweighs the hashing itself. Speed is almost never a real reason to choose MD5.

What each one is still fine for

  • MD5: detecting accidental corruption, deduplicating your own files, cache keys and ETags, and talking to legacy systems that expect it. Never for signatures, certificates, or integrity checks where an attacker could supply the file.
  • SHA-1: existing systems you cannot change yet. Git has long named objects with SHA-1, using a hardened implementation that detects known collision attacks, and also supports repositories that use SHA-256. HMAC-SHA1, the default algorithm behind TOTP authenticator codes, is not affected by collision attacks.
  • SHA-256: download checksums, digital signatures, certificates, HMAC, content addressing and anything new. Use SHA-256 when a checksum has to hold up against tampering, and keep MD5 for the legacy values you still need to match.

Checking a download? The File Checksum Checker hashes the file locally and tells you which algorithm a pasted checksum matches.

None of them should store passwords

All three are designed to be fast, and fast is exactly what an attacker guessing billions of passwords wants. A salt stops precomputed tables but does not slow the guessing down. Password storage needs a function that is deliberately slow and, ideally, memory-hard. On the same machine as above:

Function and settingsTime per password
SHA-256, one call from Nodeabout 2.5 microseconds
Argon2id, 19 MiB memory, 2 iterations, 1 laneabout 33 milliseconds
PBKDF2-HMAC-SHA256, 600,000 iterationsabout 270 milliseconds
scrypt, N=2^17, r=8, p=1about 310 milliseconds

Those settings are the minimums in the OWASP Password Storage Cheat Sheet, which recommends Argon2id first, then scrypt, bcrypt with a work factor of 10 or more for legacy systems, and PBKDF2 where FIPS-140 compliance is required. Use your framework's password hashing API rather than assembling one from a plain hash.

HMAC: when a hash needs a key

To prove that a message came from someone holding a secret, do not compute sha256(secret + message). MD5, SHA-1 and SHA-256 are all open to length extension: knowing the digest of one message lets an attacker compute a valid digest for that message with extra data appended, without knowing the secret. HMAC (RFC 2104) avoids this. HMAC-SHA256 is the standard choice, and all of these print the same value:

// Node.js
crypto.createHmac('sha256', 'secret').update('hello').digest('hex')

# Python
hmac.new(b'secret', b'hello', hashlib.sha256).hexdigest()

// PHP
hash_hmac('sha256', 'hello', 'secret')

// 88aab3ede8d3adf94d26ab90d3bafd4a2083070c3bcce9c014ee04a443847c0b

Compare HMACs with a constant-time function such as crypto.timingSafeEqual, hmac.compare_digest or hash_equals, not with ==.

Hashing on the command line and in code

# Linux (coreutils)
md5sum file.iso
sha1sum file.iso
sha256sum file.iso

# macOS
md5 file.iso
shasum -a 1 file.iso
shasum -a 256 file.iso

# Windows PowerShell
Get-FileHash file.iso -Algorithm MD5
Get-FileHash file.iso -Algorithm SHA1
Get-FileHash file.iso              # SHA256 is the default

# Any system with OpenSSL
openssl dgst -sha256 file.iso

# Hashing a string: printf adds no newline, echo does
printf '%s' hello | sha256sum      # 2cf24dba5fb0a30e...
echo hello | sha256sum             # 5891b5b522d5df08...

In the browser, crypto.subtle.digest() supports SHA-1, SHA-256, SHA-384 and SHA-512 but not MD5; asking for MD5 throws a NotSupportedError. That is why browser tools, including this site's, compute MD5 with a separate JavaScript implementation.

Frequently Asked Questions

Is SHA-256 slower than MD5?

It depends on the processor. On a processor without SHA extensions we measured about 730 MB/s for MD5 and 460 MB/s for SHA-256. Processors with SHA extensions accelerate SHA-256 enough that it can be faster than MD5, and for short strings the difference is negligible.

Is MD5 still OK for file checksums?

For catching accidental corruption, yes, because nobody can find a file that matches a given MD5. It is not OK when an attacker could have prepared the file, because MD5 collisions are cheap. Use SHA-256 when the checksum must resist tampering.

Is SHA-1 broken?

Its collision resistance is. Practical collisions were shown in 2017 and chosen-prefix collisions in 2020, so SHA-1 must not be used for signatures or certificates. HMAC-SHA1 and preimage resistance are not affected by these attacks, but new designs should use SHA-256.

Which hash should I use for passwords?

None of these three. Use Argon2id, or scrypt or bcrypt if Argon2id is unavailable. They are deliberately slow and salted, which makes guessing passwords from a stolen database far more expensive.