HashCheckr

How to verify a download with a checksum on Windows, macOS and Linux

6 min readUpdated May 2026
Two people side by side on a sofa, one holding a tablet and the other working on a laptop.

Verifying a download is three steps: get the expected checksum from somewhere you trust, compute the checksum of the file you actually have, and compare the two properly. Every operating system ships a tool for the middle step, and none of them make the first or the third step obvious. This guide gives the exact commands for Windows, macOS and Linux, the way to compare digests that does not quietly cheat, and what a signature adds if you want to go further.

First, get the expected value from somewhere you trust

This is the step people skip, and it is the one that carries the security. Take the checksum from the project's own site over HTTPS — the release notes, the download page, or a SHA256SUMS file published next to the artifacts. Ubuntu keeps one on releases.ubuntu.com; Debian publishes SHA256SUMS and SHA512SUMS per image directory; most GitHub releases either list digests in the release body or attach a checksums file to the release.

Avoid taking the digest from the same mirror that served the large file, from a forum post, or from a search result summary. If a mirror has been tampered with, a checksum hosted on it will have been updated to match. The whole point of the arrangement is that the tiny trusted value and the large untrusted file come from different places.

Windows: certutil and Get-FileHash

Windows has shipped certutil since Windows 7, and it needs no installation. In Command Prompt or PowerShell, run certutil -hashfile ubuntu-24.04.iso SHA256. It prints the digest in lowercase hex, sometimes with spaces between byte pairs on older builds, followed by a confirmation line. Replace SHA256 with MD5, SHA1 or SHA512 as needed.

PowerShell's own cmdlet is cleaner: Get-FileHash -Algorithm SHA256 .\ubuntu-24.04.iso gives you an object with an uppercase Hash property. To make PowerShell do the comparison instead of your eyes, use (Get-FileHash -Algorithm SHA256 .\ubuntu-24.04.iso).Hash -eq "PASTE_THE_EXPECTED_HASH", which prints True or False. String comparison in PowerShell is case-insensitive by default, so pasting a lowercase digest is fine.

Both tools read the file from disk at full speed, and both will happily take several minutes on a multi-gigabyte ISO stored on a slow external drive. Neither gives you a progress indicator, which is the main reason people assume the command has hung.

macOS: shasum and md5

macOS ships shasum, a Perl script that handles the whole SHA family through a single flag: shasum -a 256 ubuntu-24.04.iso for SHA-256, -a 512 for SHA-512, -a 1 for SHA-1. Output is the digest, two spaces, and the file name — exactly the GNU coreutils format, so you can redirect it into a file and reuse it later.

For MD5 the separate md5 command is the native one, printing MD5 (file) = digest — the BSD style you will sometimes see quoted on release pages. If you prefer the coreutils layout, md5 -r file reverses it to digest file.

shasum also checks a whole manifest: put SHA256SUMS next to the files and run shasum -a 256 -c SHA256SUMS. Each line is reported as OK or FAILED, and the command exits non-zero if anything failed, which makes it usable in a script.

Linux: sha256sum and the -c flag

GNU coreutils gives you one command per algorithm: sha256sum, sha512sum, sha1sum, md5sum and b2sum. Run sha256sum ubuntu-24.04.iso and you get the same digest filename line. b3sum for BLAKE3 is a separate package, available in most distributions.

The -c flag is what makes these tools worth learning. sha256sum -c SHA256SUMS reads the manifest, hashes each file it names in the current directory, and prints one OK or FAILED per line. Add --ignore-missing when the manifest lists every image in the release and you only downloaded one, and --quiet to print only failures.

A one-liner for a single file: echo "EXPECTED_HASH ubuntu-24.04.iso" | sha256sum -c -. The two spaces between the digest and the name are part of the format and are not optional — a single space makes coreutils reject the line as improperly formatted, which is the most common reason this trick fails.

Compare the two strings without fooling yourself

A 64-character hex string is hard to check by eye, and the human shortcut — glance at the first four characters, glance at the last four, decide it matches — is the one that fails. It also fails in a specific direction: it is exactly what an attacker with a partial collision would exploit, and it is exactly what a copy-paste that lost a character in the middle survives.

Let a machine compare them. On Linux and macOS the -c flag does it. In PowerShell the -eq comparison does it. In a browser, paste both into a tool that compares them character by character — this site's verify field reports which characters differ and how many, which distinguishes a mistyped checksum from a genuinely different file at a glance.

Case never matters: hex digests are conventionally lowercase on Linux and uppercase in Get-FileHash output, and the two are the same value. Whitespace does not matter either, as long as you are not silently dropping a character with it. What does matter is that you compare the entire digest against a value you fetched from the right place.

One step further: GPG signatures

A checksum tells you the file matches the digest. A signature tells you who vouched for the digest. Distributions publish both: alongside SHA256SUMS you will usually find SHA256SUMS.gpg, a detached OpenPGP signature over that text file. Verify it with gpg --verify SHA256SUMS.gpg SHA256SUMS after importing the signing key.

Getting the key honestly is the whole difficulty. Ubuntu documents the fingerprint of its signing key on its own site and ships it in the ubuntu-keyring package; Debian ships debian-keyring; Tails walks you through the whole procedure step by step. Importing a key from a keyserver and then checking its fingerprint against a value printed somewhere independent is the minimum honest version of this step.

If that sounds like a lot of ceremony for downloading an ISO, it is — and it is proportionate for an operating system you are about to install, less so for a font file. Checking a SHA-256 you fetched over HTTPS from the project's own domain already rules out the overwhelming majority of things that actually go wrong, which are mirrors, cables and disks rather than adversaries.

the takeaway

Use certutil -hashfile file SHA256 or Get-FileHash on Windows, shasum -a 256 file on macOS, sha256sum file on Linux — and prefer the -c form against a SHA256SUMS manifest whenever one exists, because it compares for you. Fetch the expected value over HTTPS from the project's own domain, never eyeball only the ends of a digest, and add a GPG signature check when the thing you are installing deserves it.

Related tool
HashCheckr · Checksum calculator

Drop a file and get its SHA-256 in seconds