Security

Which hash to use, and what each one is for

MD5 is broken and still the right choice for some jobs. SHA-256 is not the right choice for storing passwords. Here is the line between them, and the digest sizes to match.

Most writing about hash functions divides into two kinds. One kind lists algorithms and their digest lengths and leaves you to work out which one you are supposed to pick. The other kind says that MD5 and SHA-1 are broken and stops there, which leaves you stuck the moment you need a fast, cheap fingerprint for something that is not a security boundary. This piece is the missing part: what each algorithm is actually for, and where the line sits between a checksum and a security decision.

The two questions a hash answers

A hash function takes any amount of input and produces a fixed-size output. Everything else is a property you either need or do not:

  • Preimage resistance. Given the digest, you cannot work back to the input. Every hash on this page has this, including MD5. It is the weakest property and the one people mean when they say a hash is "one-way".
  • Second preimage resistance. Given one input, you cannot construct a different input with the same digest. This is what stops someone swapping a file for a lookalike.
  • Collision resistance. You cannot construct any two inputs with the same digest. This is the strongest property, it is the one MD5 and SHA-1 lost, and it only matters when the person choosing the inputs is not you.

That last sentence is the whole decision. If the inputs are yours — you are fingerprinting files you already have, or computing a cache key — a collision does not help anybody, and a broken collision resistance costs you nothing. If the inputs come from an adversary, or from a document someone else could swap out, collision resistance is the property you are buying and MD5 has none left to sell.

What each algorithm is worth

Algorithm Digest Hex length Status
MD5128 bits32Collisions since 2004. Fine as a checksum.
SHA-1160 bits40Collisions demonstrated in 2017. Retired.
SHA-256256 bits64The default. No practical attack.
SHA-384384 bits96Truncated SHA-512 with a different starting value.
SHA-512512 bits128Often faster than SHA-256 on 64-bit hardware.
SHA3-256256 bits64A different construction. Immune to length extension.
BLAKE2bUp to 512 bitsUp to 128Fast, modern, no length-extension weakness.
BLAKE3256 bits, extensible64Very fast, parallel, tree-based.
CRC3232 bits8Not a cryptographic hash at all.
Argon2idConfigurableVariesFor storing passwords. Not for anything else.

Digest size is not the same thing as security level, which is why SHA-1's 160 bits were never the problem. Attacks on a cryptographic hash are named for the work factor: a preimage attack against an n-bit digest costs about 2n, while a collision attack costs about 2n/2 because of the birthday bound. SHA-1's 160 bits therefore gave at most 80 bits of collision resistance in theory, and in practice considerably less.

Choosing one, by job

Fingerprinting files you already have

MD5 and SHA-1 both do this well and always have. They are fast, they are implemented everywhere, and a collision requires an attacker who can choose both inputs. If you are computing a digest of a file sitting on your own disk to check it copied correctly, or to name a cache entry, MD5's speed is a real advantage and its weakness is unreachable.

The moment the file came from somewhere else, the calculus flips. Publishing a download alongside its MD5 is asking the reader to trust a check that a determined attacker can forge, and the fix costs nothing: publish a SHA-256 instead. If compatibility forces you to offer MD5, offer both and say which one to check.

Verifying a download

Use SHA-256 or SHA-512, and understand what the check actually proves. A digest published on the same page as the file protects you against a corrupted transfer and against a mirror serving something different. It does not protect you against the publisher being compromised, because whoever replaced the file could replace the digest beside it. For that you need a signature, which is a different tool doing a different job: the digest proves the file arrived intact, the signature proves who produced it.

Storing passwords

None of the algorithms above belong anywhere near this job, and the reason is speed. A hash designed to fingerprint a gigabyte in a second is a hash that will compute billions of candidate passwords per second on a graphics card. Password storage needs the opposite property: an algorithm that is deliberately slow, and deliberately memory-hungry, so that parallelism buys an attacker little.

ChoiceCost per guessNotes
SHA-256, unsaltedMicrosecondsDo not. Identical passwords produce identical digests.
SHA-256, saltedMicrosecondsKills rainbow tables, still trivially parallel.
PBKDF2TunableWidely available. Raise the iteration count as hardware improves.
bcryptTunableMemory-light, truncates input at 72 bytes.
scryptTunableMemory-hard. Cost parameters are easy to under-set.
Argon2idTunableThe current recommendation. Memory-hard and side-channel resistant.

The parameters matter as much as the algorithm, and the practical target is a moving one: a well-configured password hash should take somewhere around a tenth of a second on the hardware your service actually runs on. Much faster than that and you have left strength on the table; much slower and you have built a denial-of-service vector pointed at your own login form.

Signing something

A plain hash is not a signature and cannot be made into one by keeping the key secret. The naive construction — hash the message, append a secret, hash again — is vulnerable to a length extension attack, in which an attacker who knows the digest of one message can compute a valid digest for that message with extra data glued to the end. secret + message and message + secret are both wrong in different ways. Use HMAC, which is a construction specifically designed to close that hole, and use it with SHA-256 or better.

The algorithms that are not vulnerable to length extension are worth knowing about for this reason: SHA-3 and BLAKE2 both use constructions that resist it structurally. If you are designing a protocol from scratch rather than using one that already exists, BLAKE2 or BLAKE3 are reasonable defaults — BLAKE3 in particular is dramatically faster than SHA-2 for large inputs because it splits the work across a tree instead of hashing a stream from front to back.

Two things that trip people up

Encoding is not hashing. Base64 shows up in the same conversations constantly, and it does something completely different: it re-spells bytes using a 64-character alphabet so they survive a trip through a text-only channel. It is reversible by anyone, with no key and no work. Seeing a string that ends in = tells you nothing about whether it is a digest or an encoded payload, and treating an encoded payload as if it were protected is a mistake that has shipped in real software.

Truncation is a choice, not a free lunch. Taking the first sixteen hex characters of a SHA-256 digest gives you a 64-bit fingerprint that is fine for deduplicating a few million files. Do the arithmetic before you commit to it — at 64 bits, the birthday bound puts a likely collision somewhere around four billion items, and the consequence of a collision in a deduplicating store is that two different files share one slot. Short digests are perfectly reasonable when you have counted the items and unreasonable when you have not.

Where the tools fit. The Hash Generator computes MD5, SHA-1, SHA-256, SHA-384 and SHA-512 from text or a file, so you can see how the digest lengths above behave on real input — and watch a single character change the whole output.

If what you actually need is a password rather than a digest, the Password Generator is the right page, and if you need to move bytes through a text channel, that is Base64 — a reversible encoding, with no security property whatsoever.

The rule

Ask what the hash is protecting against. If the answer is "nothing in particular, I just need a fingerprint", any of them will do and speed should decide. If the answer involves an adversary who chooses the input, you need collision resistance, which rules out MD5 and SHA-1 and points at SHA-256 or better. If the answer is "a password", you need none of them — you need a slow, memory-hard function whose cost you have actually tuned. Three different jobs, three different answers, and the digest length is the least interesting thing about any of them.