Verifying Downloads

How to check a file has not been tampered with on Mac

Nobody can edit a file and leave its fingerprint where it was, which is what makes a digest the one claim about a file worth anything at all. Producing one is the easy half and Rocket Hash does it in seconds; getting hold of a trustworthy value to compare it against is the half that decides whether you have proved anything.

The Finder tells you the file was last modified at 14:02 on a Tuesday in March. That is not evidence. It is a field, and touch rewrites it in less time than it took you to read this sentence. The same goes for the size, the icon, the file name and the folder it is sitting in: every one of them is easier to change than the thing they are supposed to describe.

A digest is different, because it is computed from the data rather than stored alongside it. Change one byte anywhere in the file — a bit in a video frame, a line in a script, an instruction in an installer — and roughly half of the digest's bits change with it, which in hexadecimal leaves almost none of its characters as they were.

That is the strong half of the claim, and it is why people reach for checksums when they are worried. The weak half is the part this page is mostly about: a fingerprint is only evidence when you can trust the copy of the fingerprint you are comparing against. Get that wrong and you have performed a ritual, not a check. If you want the mechanics of producing and comparing a digest first, checking a file’s checksum covers those in a few minutes; this page is about when the answer means something.

Same page, same server, same proof of nothing

A checksum published next to the download, served by the same machine over the same connection, tells you the transfer was not corrupted. It is not evidence about where the file came from, because anybody able to replace the file can also replace the number printed beside it.

What a digest detects, and what it cannot

Worth being exact about both lists, because the gap between them is where people get into trouble.

It detects any change to the file’s data, of any size, whatever caused it. One flipped bit from a failing cable and a deliberately patched binary are equally visible; the arithmetic has no notion of intent and no threshold below which a change is too small to register.

It does not detect, or say anything at all about:

  • When the change happened. A digest is a snapshot with no clock in it. Two mismatching values tell you the file is not what it was; only your own records say when it stopped being that.
  • What changed. There is no partial information in a digest — no indication whether one byte moved or the whole file was replaced. For that you need the old copy and a comparison tool.
  • Who did it. Nothing in a digest is tied to an identity. That is the job of a signature.
  • Anything outside the data. Permissions, Finder tags, extended attributes and dates are not hashed, so a file whose dates were rewritten but whose contents were left alone verifies perfectly.
  • Whether the file was ever any good. An unmodified copy of a malicious installer matches its published checksum exactly. Integrity is not safety, and the two are routinely confused.

The one condition the whole thing rests on

To be evidence of anything, the value you compare against has to satisfy two requirements. It must come from somewhere the person who might have altered the file could not also reach, and it must have been recorded before the alteration you are worried about. Neither is automatic, and reference values vary enormously in how well they manage it.

Sources of a reference checksum and what each one can prove
Where the checksum came fromWhat a match actually proves
The same page as the downloadThe transfer was not corrupted. Nothing about the file’s origin.
A different channel — the vendor’s documentation, a release announcement, a colleague reading it out, a value you wrote down last yearThe file matches what that channel said, so an attacker would have needed to reach both.
A digest you recorded yourself, before the file was ever exposedThe file is byte-for-byte what you had. The strongest statement available for your own material.
A signature over the digest, verified with a key you already hadThe file is the one the holder of that key published. The only form that scales to strangers.

This is why Linux distributions publish a SHA256SUMS file and a detached signature beside it rather than just a list of numbers: the list makes verification cheap, and the signature is what makes the list worth verifying against. Verifying a Linux ISO shows the two working together, and publishing a checksum for a file you share is the same problem from the other side of the transaction.

Fingerprinting your own files first

For files that originate with you, the trust problem largely dissolves: you can be the trustworthy channel. Hash the material while it is still only yours — before it goes on the shared volume, before the contractor gets access, before the laptop travels — and keep the digests somewhere the file’s future custodians cannot write to.

That last clause is the one people skip. A list of digests stored in the same folder as the files it describes protects against accidents and not against anybody, because somebody who can rewrite the files can rewrite the list in the same breath. A printed page, a note in a password manager, a commit in a repository somebody else also pulls from: any of those is harder to quietly amend than a text file sitting next to the data. Rocket Hash will produce the list from a folder of a hundred thousand files in one pass; where you put it afterwards is the part that decides whether it means anything.

The same habit used across years rather than across custody is how you catch silent decay instead of interference, which is the subject of verifying a backup.

Why the algorithm matters here, and rarely elsewhere

For catching a bad download, any of the eight algorithms works and the choice is a detail. For tamper-evidence it is not a detail, and the reason is a distinction that sounds academic right up to the moment it decides your answer. Hash functions are asked to resist three different things:

  • Preimage resistance. Given a digest and nothing else, you cannot find any input that produces it. This is what makes a digest safe to publish.
  • Second-preimage resistance. Given one specific file, you cannot find a different file with the same digest. This is the property that stops somebody substituting a file for one you already hold.
  • Collision resistance. You cannot find any two different files that share a digest, when you are free to choose both of them. The attacker authors both halves.

Which property you are leaning on depends entirely on who chose the original file — and this is where MD5 and SHA-1 stop being interchangeable with the rest.

If you fingerprinted the file yourself and somebody wants to slip a different one past your recorded value, they need a second preimage: a new file matching a digest that was fixed before they arrived. No practical second-preimage attack is known against MD5 or SHA-1. The famous breaks against both are collision attacks, which is a different problem, so an MD5 baseline you recorded yourself genuinely would still catch a substitution.

If the file came from somebody you are not sure about — or if an attacker had a hand in preparing the “good” version as well as the bad one — they need only a collision, and they get to design both files. MD5 collisions have been constructible since 2004 and now take seconds on an ordinary laptop. SHA-1 collisions stopped being theoretical in 2017, when a pair of different PDF documents sharing one SHA-1 digest was published as the SHAttered result; by 2020 the more dangerous chosen-prefix variety was within reach of tens of thousands of dollars of rented computing. In that scenario a matching MD5 or SHA-1 proves nothing whatsoever, because both halves of the pair were built to match.

Whether each algorithm is suitable as evidence against deliberate tampering
AlgorithmDigest lengthCollision statusUse as tamper-evidence?
CRC328 hex charactersForging one is arithmetic, not an attackNever
MD532Trivially constructible since 2004No
SHA-140Demonstrated publicly in 2017No
SHA-25664None known or expectedYes — the default
SHA-512128None knownYes
SHA3-256 / SHA3-51264 / 128None knownYes, on a different construction

The practical conclusion is short. Use SHA-256, stop thinking about it, and note that it costs nothing to do so: the disk is the limit in both cases, and the time you save with a faster algorithm is a rounding error. Is MD5 still safe and is SHA-1 still safe go through what each one is still legitimately used for, which is more than the table suggests.

What macOS already checks for you

For applications, you are not the first line of defense and should not behave as though you were. A Mac app from a registered developer is signed, and most are notarized as well; the system verifies that signature before the app runs, which covers every file in the bundle and binds the whole thing to a developer identity in a way a published checksum cannot. If somebody patches an app after installation, that check is what notices.

Where that leaves a gap is everything that is not an app. A firmware image, a PDF, a video master, a spreadsheet, a tarball of source, a virtual machine disk — none of those carry a signature macOS knows how to check, and for them a digest really is the mechanism you have. It is also the right tool for an installer you have downloaded but not yet opened, since a checksum can be compared before anything is allowed to run.

In the window that shape is two sittings rather than one. Hash the file in Files while you still trust it and keep the digest with your records; when the question comes up, hand the file and that recorded value to Against a Checksum in Verify and read the seal. The second sitting takes seconds; the first one was the part doing the work.

Two downloads beat one

When a publisher offers no checksum at all, you can still raise the bar: fetch the file twice, from two different networks or two different machines, and compare the copies against each other. Matching copies do not prove the file is honest, but they rule out interference aimed at you specifically.

Troubleshooting

The digest does not match and I cannot explain it

Work through the boring causes before the frightening one, because the boring ones are overwhelmingly more common: an incomplete download, the wrong file in a folder of similar names, a checksum for a different build or a different architecture, or two different algorithms being compared. What to do when a checksum does not match is the ordered list. What you should not do is install it anyway and resolve to keep an eye on things.

The digest changed but nobody edited the file

Plenty of software rewrites a file simply for having been opened. PDF editors renumber internal objects, office applications update their own metadata on save, photo tools re-encode on export, and some sync clients normalize files on upload. None of that is tampering, and all of it changes the bytes. Before concluding anything, find out whether the file has been opened by an application that writes.

The only checksum I can find is an MD5

Then use it, and understand its shape. Against corruption it is as good as anything. Against a substitution of a file you already fingerprinted yourself it is still sound, because that needs a second preimage. Against a publisher who might be the problem, or a file built to collide, it is worth nothing — so if the stakes are real, ask for a SHA-256 rather than talking yourself into the 32 characters you have.

The file verified and the system still will not open it

Those are two separate checks reaching two separate conclusions, and both can be right. A digest says the bytes are the bytes the publisher distributed; the system’s own signature and notarization checks say something about who published them and whether that identity is in good standing. An unsigned download from an honest developer fails the second while passing the first. Treat the checksum as confirming delivery, not as overriding Gatekeeper.

I need to know exactly what changed

A digest cannot tell you, by design — it is a fixed 64 characters whether the file is a kilobyte or a terabyte, so there is no room in it for a description of the difference. What it can do is narrow the search. Hash the whole folder and compare the result with the list you took before: every digest that still matches is a file you can stop looking at, which usually leaves one. Checking files against a manifest is that job end to end. Which bytes moved inside that one file is a separate question, and not one a fingerprint can answer.

Frequently asked questions

How can I tell if a file has been modified on my Mac?

Compare its current digest with one recorded earlier, from a source that has not been under the control of whoever might have changed the file. Any difference in the data — a single bit or a complete replacement — flips about half the bits of the digest, so the comparison is unambiguous. Without an earlier reference value there is nothing to compare against, and the file’s own modification date is not a substitute because that can be rewritten at will.

Can a file’s modification date be faked?

Yes, in one command and without any special privileges — the date is metadata stored next to the file rather than anything derived from its contents. The same is true of the size shown in the Finder once a file has been deliberately padded. Dates are useful as a hint about what to look at and worthless as proof.

Can someone change a file and keep the same checksum?

Not for a digest that was fixed before they started: that would require a second preimage, and no practical second-preimage attack exists against any of the common algorithms, MD5 and SHA-1 included. The real danger is different — if an attacker gets to author both the innocent file and the replacement, they can build two files that share a digest. That is a collision, it is cheap against MD5 and demonstrated against SHA-1, and it is why tamper-evidence should use SHA-256.

Does a matching checksum mean the file is safe?

No. It means the file is identical to the one the checksum describes — which is excellent news if that file was trustworthy and no help at all if it was not. A pristine, perfectly verified copy of malware matches its own digest every time. Integrity and safety are separate questions and a hash only answers the first.

Is MD5 good enough to detect tampering?

It depends on who chose the file. Against accidental corruption MD5 is fine, and against someone substituting a file for one you fingerprinted yourself it still holds, because that requires a second preimage rather than a collision. Against a file whose author may be the problem it fails, because MD5 collisions have been constructible since 2004. SHA-256 removes the need to reason about which case you are in.

Where should I get a checksum from so it actually proves something?

From anywhere that is not the same place as the file. A value on the download page, served by the same machine over the same connection, only shows the transfer worked, because anyone who can replace the file can replace that number too. A vendor’s separate documentation, a release announcement, a digest you recorded yourself beforehand, or best of all a signature over the checksum that you verify with a key you already trust — each of those forces an attacker to compromise two things instead of one.

Can a checksum tell me what part of a file changed?

No. A digest is the same fixed length for every input, so it carries no information about the nature or the location of a difference — only that there is one. Across a folder it still narrows things usefully: hashing every file and comparing the result with an earlier list tells you which file changed, even though no digest can say where inside it. Finding the altered bytes in that one file needs both versions side by side, which is a separate job from verifying.