# 08 DEC 2025 · SECURITY

Checksums, explained: why every download should come with a SHA-256

What a SHA-256 checksum is, what it protects you from and what it does not, and how to check one on macOS, Linux and Windows in a few seconds.

>_[ FIG. 00 · SECURITY ]×
A release file passes through SHA-256 to a 64 character digest that matches the published value, while a copy with one changed bit produces a completely different digest that does not match SHA-256, CHECKED IN ONE DIRECTION DOWNLOADED FILE SHA-256 ONE WAY 285b17505b8be27d7f12ec27b0f1f1e5 6b212dad67b69b2d4c694d1cbbdefdce COMPUTED 285b17505b8be27d7f12ec27b0f1f1e5 6b212dad67b69b2d4c694d1cbbdefdce PUBLISHED .SHA256 SAME FILE, 1 BIT OFF SHA-256 ONE WAY 293ea6a5fcc8a7aac7bf74dcad4516b2 5b95fb74a9a6c2e1cc19aede63fef188 COMPUTED MATCH MISMATCH INSTALL DO NOT INSTALL 1 2 3 4 5 KEY 1 ANY FILE, ANY SIZE 2 HASH FUNCTION. EASY FORWARD, NOT BACK 3 256 BITS, SHOWN AS 64 HEX CHARACTERS 4 THE VALUE THE PROJECT PUBLISHED 5 ONE BIT CHANGED. NO CHARACTER SURVIVES COMPARE ALL 64, NOT JUST THE ENDS DIAGRAM · EXAMPLE DIGESTS

Next to many download links there is a long string of letters and numbers, or a small file ending in .sha256. Most people scroll past it. That string is a SHA-256 checksum, and checking it takes about ten seconds. This post explains what a checksum is, what it protects you from, what it does not protect you from, and the exact commands to check one on macOS, Linux and Windows.

We care about this because we ship small tools as downloads, and every one of our release files comes with a matching .sha256 file. We would like more people to use them, and to understand what they are actually getting when they do.

What a hash is

A cryptographic hash function takes any input, a ten-byte text file or a four-gigabyte disk image, and turns it into a short fixed-length value called a digest. For SHA-256 the digest is 256 bits long, which is usually written as 64 hexadecimal characters.

Three properties make it useful:

  • It is deterministic. The same bytes always give the same digest, on any machine, with any correct implementation.
  • It is one way. Given a digest, there is no practical way to work back to a file that produces it.
  • Small changes spread everywhere. Flip a single bit anywhere in the input and roughly half the bits of the digest change. The drawing at the top shows this. The two files differ by one bit, and the two digests share nothing you could spot by eye.

The last property is why a checksum is such a good test for "is this the same file". There is no such thing as a nearly matching digest. It matches or it does not.

SHA-256 is part of the SHA-2 family, published by NIST in 2001. It has no known practical attacks. Older functions are a different story. MD5 has been broken for collisions for about twenty years, and researchers produced a real SHA-1 collision in 2017. If a project still publishes only MD5 or SHA-1 values, treat them as a check for accidental corruption and nothing more.

What a checksum protects you from

The honest answer is: mostly accidents, and some kinds of tampering.

Corrupt downloads. A connection drops and the browser saves a truncated file. A flaky Wi-Fi link or a bad proxy mangles a few bytes. A disk or USB stick has a failing sector. Any of these leaves you with a file that looks fine in Finder or Explorer and fails in strange ways later. A checksum catches all of them immediately.

The wrong file. It is easy to grab the Intel build when you wanted the ARM one, or last month's release instead of this one. The digest will not match the one you meant to download.

A swapped file on a mirror or CDN. If the file comes from one place and the checksum from another, someone who can replace the file on the mirror still has to make it match a value they do not control. With SHA-256 they cannot.

That last point depends on the checksum coming from somewhere the attacker cannot also change, which brings us to the limits.

What it does not protect you from

A checksum tells you that your file matches a published value. It says nothing about whether the published value is honest.

If an attacker gets control of the release page itself, they can upload a malicious file and publish its correct SHA-256 right next to it. Your check will pass, because the file really does match. The same goes for a compromised build machine that produces a bad binary before anyone hashes it. A checksum proves integrity (the bytes are the ones that were published). It does not prove authenticity (the bytes came from the people you think, and they meant to publish them).

Authenticity is what signatures are for. A digital signature is made with a private key that only the publisher holds, and anyone can check it with the matching public key. Replacing the file and the checksum is not enough to fake one. You also need the key. Operating systems use this idea all the time: macOS checks code signatures and Apple's notarisation, and Windows checks Authenticode signatures on executables and installers. For plain files there are tools such as GPG, minisign and Sigstore.

So a sensible way to think about it:

  • A checksum over HTTPS from the project's own site catches corruption and most mirror problems. It is quick, and it costs you nothing.
  • A signature, or an operating system's signing check, is what protects you if the release channel itself is compromised.
  • Neither tells you whether the software is any good. That part is still trust in the people who wrote it.

We are not trying to talk anyone out of checksums here. Most real-world download problems are the boring kind, and a checksum stops those completely.

How to check a SHA-256 on macOS

macOS ships with shasum, a Perl script that supports the whole SHA family. Open Terminal and run it with the file's path:

shasum -a 256 ~/Downloads/app-macos-aarch64.tar.gz

It prints the digest followed by the file name. Compare that digest with the published one. You can drag the file from Finder into the Terminal window instead of typing the path.

If you downloaded the .sha256 file too, and it uses the usual "digest, two spaces, file name" format, shasum can do the comparison for you. Run it from the folder that holds both files:

cd ~/Downloads
shasum -a 256 -c app-macos-aarch64.tar.gz.sha256

It prints OK or FAILED for each file listed.

How to check a SHA-256 on Linux

Almost every Linux distribution includes sha256sum from GNU coreutils (on Alpine and other BusyBox systems there is a compatible version):

sha256sum app-linux-x86_64.tar.gz

To check against a published file, use -c, again from the folder that holds both files:

sha256sum -c app-linux-x86_64.tar.gz.sha256
app-linux-x86_64.tar.gz: OK

One thing that catches people: -c expects the file name to be inside the .sha256 file. Some projects publish a bare digest with no name after it, and then -c complains about a badly formatted line. In that case, print the digest yourself and compare the two strings. The same trick works on a SHA256SUMS file that lists many downloads. Add --ignore-missing and it checks only the files you actually have.

How to check a SHA-256 on Windows

PowerShell has Get-FileHash built in. SHA-256 is the default algorithm, but it does no harm to say so:

Get-FileHash .\app-windows-x86_64.zip -Algorithm SHA256

It prints the digest in upper case. That makes no difference, since hexadecimal is not case sensitive, but it does make comparing by eye a little harder. You can let PowerShell compare for you. The -eq operator ignores case for strings:

$actual = (Get-FileHash .\app-windows-x86_64.zip).Hash
$expected = (Get-Content .\app-windows-x86_64.zip.sha256).Split(' ')[0]
$actual -eq $expected

That prints True or False. If you are in the older Command Prompt, certutil does the same job:

certutil -hashfile app-windows-x86_64.zip SHA256

Habits that make it worth doing

A checksum you glance at is weaker than one you compare. People tend to check the first four and last four characters, and that is usually enough to catch a truncated download. It is not enough against someone who is trying. If you care about tampering, let the tool do the comparison with -c or -eq, or paste both values into a text editor and search for one inside the other.

Get the checksum over HTTPS, from the project's own site or release page, not from a forum post or a mirror's copy. Check before you run or install anything, not after. And if the check fails, delete the file and download it again. A mismatch is almost always corruption, but there is no reason to find out the other way.

For our own desktop apps and security tools, every release file has a matching .sha256 next to it. dskcopy also uses SHA-256 after writing a disk image, so it can tell you whether what landed on the drive is exactly what you started with. That is the same idea from the other direction. First you check the file you downloaded, then you check the copy you made.