Settings

What the hash is doing

A cryptographic hash reads every byte of a file and produces a fixed-length number from them. SHA-256 produces 32 bytes, written as 64 hexadecimal characters. The length never changes: a six-byte file and a six-gigabyte file both come out as 64 characters.

The property that makes it useful is that the output has nothing to do with the input in any way you could work backwards or steer. A file holding hello and a newline, six bytes in all, hashes to:

5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03

Change the o to a p — one byte, in a six-byte file — and it becomes:

bf8c83416f31143ee2fa5db7ebbbb54589626c4c2046a91d28545bc403e3cda6

136 of the 256 bits are different, which is what you would get from two unrelated numbers. There is no partial match and no "close". This is why comparing hashes works as a check: you are not looking for similarity, you are looking at whether two 64-character strings are the same string.

The lengths are worth knowing, because the length tells you which algorithm produced a value you were handed: SHA-1 is 40 hex characters, SHA-256 is 64, SHA-384 is 96, SHA-512 is 128. CHECKSUM uses exactly that to switch itself to the right algorithm when you paste an expected value, rather than comparing a SHA-512 against a SHA-256 and announcing a mismatch.

Why SHA-256 and not MD5

A collision is two different inputs with the same digest. Collisions have to exist — there are more possible files than there are 256-bit numbers — but for a hash to be any use, nobody must be able to find one. MD5 fails that, and not narrowly.

The best-known MD5 collision is a pair of 128-byte messages differing at six byte positions: 19, 45, 59, 83, 109 and 123. The first of those differences falls inside the opening twenty bytes.

A  d131dd02c5e6eec4693d9a0698aff95c2fcab587 …
B  d131dd02c5e6eec4693d9a0698aff95c2fcab507 …

MD5(A) = MD5(B) = 79054025255fb1a26e4bc422aef54eb4

Their SHA-256 digests, over the same bytes, are 8d12236e… and b9fef2a8…, which is what two different files are supposed to look like.

It gets worse in the way that matters for downloads. MD5 works through a file in fixed-size blocks, carrying an internal state forward, so once two inputs have collided that state is identical and stays identical for anything appended to both. Sticking the same 51-byte invoice line on the end of each of those messages gives two 179-byte files that still share one MD5, 1ae043fb16bf2ea27533a880ce17c025. The colliding block is the price of admission; the rest of the file is then free. That is why a published MD5 no longer proves anything about a deliberate substitution, though it will still catch a truncated download.

No collision has ever been published for SHA-256. SHA-1 is in the same position as MD5 and should be treated the same way; CHECKSUM still accepts a 40-character value because publishers still post them, not because posting them is a good idea.

A browser's own cryptography reflects this. The Web Crypto digest function every tool here calls offers SHA-1, SHA-256, SHA-384 and SHA-512 and nothing else; asking it for MD5 throws an unrecognised-algorithm error. If you want an MD5 you have to go elsewhere for it.

Where the expected value has to come from

Hashing your copy tells you what you have. It becomes a check only when you compare it with a value that came from somewhere, and that somewhere is the entire strength of the check.

Publishers usually put it in one of three places: printed beside the download link, in a checksums file alongside the release (a SHA256SUMS file is one line per file, the 64 hex characters, two spaces, the file name), or in signed release notes. The first is the weakest by a long way. If an attacker can replace the file on the download page, they can replace the line of text on the download page, and you have carefully confirmed that the file you got is the file they wanted you to get.

A hash is worth as much as the independence of the channel it arrived on, so prefer one that reaches you a different way: a checksums file with a detached signature, a value in a mailing-list announcement, a value somebody else has already published. Comparing the hash of a download against a value pulled from the same compromised page is the check people most often actually perform, and it is the one that proves least.

Whatever the source, do the comparison somewhere you control. CHECKSUM reads the file in the browser tab, computes the digest there and compares it against what you paste. It never uploads the file, which is the point: a service that wants your file in order to tell you nothing changed has already made something change hands. The same digests come out of sha256sum on Linux, shasum -a 256 on macOS and Get-FileHash in PowerShell, and using a tool you already had is better than trusting ours.

What a signature adds that a hash cannot

A hash says two files are identical. It says nothing about who made either of them: anyone can hash an altered file and publish the new digest with a straight face. A signature closes exactly that gap, by binding a digest to a private key.

A signed PDF shows the shape of it clearly. The signature dictionary carries a /ByteRange array of offset-and-length pairs saying which bytes of the file it covers, and a PKCS#7 blob whose signed attributes include a messageDigest. PDFSIG hashes exactly the bytes those ranges name, with the algorithm the signature itself declares, pulls the messageDigest out of the DER, and compares the two numbers. Where the signature is RSA, it also checks the signature over those attributes against the public key in the certificate that came with the file.

The gaps matter as much as the coverage. A signature can never cover its own /Contents, so there is always one hole and it is expected. Any other bytes outside the ranges were appended afterwards, which is how a PDF is edited, and PDFSIG lists them and the objects defined inside them.

What that gets you is narrower than it sounds, and the page says so in those words: it does not build a certificate chain, it does not check revocation, and it cannot tell you the signer is the person the certificate names. A certificate inside a file is a claim made by whoever made the file. The arithmetic says the holder of a key signed these bytes; deciding whether that key belongs to anyone you trust is a separate question that no amount of hashing answers.

What a matching hash does not tell you

Not that the file is safe. A digest is a statement about bytes, not about behaviour. If the publisher shipped malware, or the build was compromised before the hash was taken, the hash matches perfectly and always would have. Verifying an installer tells you it is the installer they published; whether they should be trusted is not a question arithmetic can reach.

Not when. A record you make of a file's digest carries the clock of your own machine, and your clock is yours to set. PROOF records the SHA-256 of a whole set of files and says this in the manifest itself. To give a date force, the digest has to reach someone else who will date its arrival — an email, a filing, a public post. That is one message, and it turns your assertion into something a third party can speak to.

Not who. Anyone holding a set of files can produce a manifest for it, including someone who altered them first. A record shows that something changed between two points in time; it does not say whose hand did it.

Nothing about the parts you did not hash. A hash covers the bytes given to it. A signature covers the byte ranges it names. Checking one file in a folder says nothing about the other forty, which is why PROOF hashes the set and then takes a single SHA-256 over the sorted list of digests, sizes and paths, so one short string identifies the whole collection.

What this is, and what it is not

A hash is about bytes, and only about bytes. It answers one question: are these two files the same file. It has nothing to say about where a file came from, who made it, when, or whether running it is a good idea.

The expected value is the weak part. The digest you compute is arithmetic and cannot be argued with. The digest you compare it against arrived from somewhere, and a check is worth no more than the independence of that channel.

Use SHA-256, and take a 40-character value as a warning. MD5 and SHA-1 will still catch a corrupted download. Neither one will catch a substitution made by somebody who wanted it to go unnoticed.

Nothing is uploaded. CHECKSUM, PROOF and PROVENANCE read files inside the browser tab and compute every digest there. No file and no hash is sent anywhere, which is also why they work with the network off.

Check with a tool you already had, when it matters. sha256sum, shasum -a 256 and Get-FileHash produce the same digests. A match from software you chose independently is worth more than a match from ours.

Questions people ask

What does a matching hash actually prove?

That the file you have is byte-for-byte the file the digest was taken from. That is a strong statement about the bytes and a statement about nothing else. It does not say the file is safe, does not say who produced it, and does not say when.

Is a hash published on the download page any use?

Some, but less than it appears. It catches a corrupted or truncated download, and a mirror serving the wrong file. It does not catch anyone who could change the page, because that person could change the hash printed on it as easily as the file linked from it.

Why not MD5, if I only want to check the download worked?

For that narrow purpose MD5 is adequate, and this is the one job it can still do. The trouble is that a digest looks equally authoritative whichever algorithm made it, so an MD5 in a place where a reader expects proof is a check that quietly stopped meaning what it used to.

What is the difference between a checksum and a signature?

A checksum says two files are identical. A signature says somebody holding a particular private key vouched for a particular digest, which a hash on its own can never say, since anyone can alter a file and publish the new hash beside it. A signature moves the question from the bytes to the key, and then to whether you have any reason to trust the key.

Does renaming, copying or moving a file change its hash?

No. The digest is computed over the contents, so the name and the location are irrelevant. Opening a file in an application and saving it does change it, often even when nothing was edited on screen, which is why you hash first and then work on a copy.

How do I record that a set of files has not changed?

Hash all of them and keep the list. PROOF does this as a manifest: a SHA-256 for each file, sorted by path, plus a single digest over that whole list so one short string identifies the set. Later, point it at the files again and it names what is unchanged, altered, missing or new.

Related tools