SSD Nodes Learn Hosting plans →
How to do am Matt ConnorBy Matt Connor · Updated 2026-08-29

How to verify download checksum for Linux

Use sha256sum to compare a file with SHA256SUMS, then change one byte and see the verification fail. Learn exactly what checksums prove.

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, August 12, 2026.

Download wey checksum verify in two minutes

To verify download with checksum, hash the file wey you receive, then make tool compare that hash with the one wey publisher print. sha256sum dey handle both parts: by itself, e go print digest, and with -c, e go read list of digests and report which files match. This guide go run the complete process on file wey you create, then spoil that file on purpose so you go see the failure happen instead of only reading about am.

Keep one sentence for mind throughout. Checksum dey tell you whether the bytes wey you get na the same bytes wey produce the digest, but e no tell you anything about who produce dem. That second question need signature and key wey you trust. The last part of this guide go show exactly where the difference between both dey.

Make file wey you fit practise with

Work inside scratch directory so nothing for here go affect the rest of system. Every command for below come from GNU coreutils, the basic command set wey dey present for any Ubuntu or Debian server, so you no need install anything.

mkdir -p ~/checksum-demo
cd ~/checksum-demo
printf 'the payload of a totally ordinary download\n' > payload.txt
sha256sum payload.txt

You go see one line: 64 hexadecimal characters, two spaces, then the file name. Those 64 characters na the file digest. Run the command again and the line go remain the same, because hashing dey deterministic: the same input always dey give the same output. Change one character for the file and run am again, and the digest no go shift small. E go look completely different, because changing one input bit dey change about half of the output bits. Na this property make 64-character string fit stand in for 4 GB image.

Save SHA256SUMS file, then check am

Hash wey dey screen no go useful after one day. Write am inside file, for format wey sha256sum dey write by itself, so tool fit read am later.

sha256sum payload.txt > SHA256SUMS
cat SHA256SUMS
sha256sum -c SHA256SUMS

sha256sum -c dey read each line for the list, hash the file name wey dey that line, then compare both hashes. If everything correct, e go print one line for each file:

payload.txt: OK

Check exit status too, because script dey read am and e no dey read the text. echo $? dey print 0 after clean run. The name SHA256SUMS na convention, e no be rule. But distributions and most release pages dey use am, so use am too. This one go make the next person know wetin dey inside the file without opening am.

Change one byte and watch the check fail

Now intentionally spoil the file. This command go write one byte for offset 5 and leave everything else as e be, so the file length and name go remain the same.

printf 'X' | dd of=payload.txt bs=1 seek=5 conv=notrunc status=none
cat payload.txt
sha256sum -c SHA256SUMS

conv=notrunc na the flag we need: if you no use am, dd go cut the file for the point wey e stop writing, and you go dey test a more obvious type of damage. The check now go print:

payload.txt: FAILED
sha256sum: WARNING: 1 computed checksum did NOT match

echo $? prints 1. FAILED mean say the file don read, but the digest no match the one wey dey the list. Put the original bytes back, then confirm say the check don return to OK:

printf 'the payload of a totally ordinary download\n' > payload.txt
sha256sum -c SHA256SUMS

Na the whole habit be this. If one byte differ anywhere for the file, e go produce FAILED. Download wey dropped connection cut short, mirror wey serve yesterday's build, proxy wey rewrite the file as e dey pass through, or disk wey return bad block: all of dem go end for that same line.

When list get file name wey you no download

A real SHA256SUMS file from a distribution dey list every image wey the project release, and you download one of dem. Make we reproduce that situation here.

printf 'a second file\n' > notes.txt
sha256sum payload.txt notes.txt > SHA256SUMS.all
rm notes.txt
sha256sum -c SHA256SUMS.all
payload.txt: OK
sha256sum: notes.txt: No such file or directory
notes.txt: FAILED open or read
sha256sum: WARNING: 1 listed file could not be read

FAILED open or read na different failure from FAILED, and if you mix dem up, you go waste time. FAILED mean say the bytes no correct. FAILED open or read mean say sha256sum never get the file at all, so nothing get compared. For real download, the usual cause na working directory, because the names for the list dey relative to where you run the command. Change go the directory wey hold the file, then run am again. To check only the file wey you actually get, ask for this:

sha256sum --ignore-missing -c SHA256SUMS.all

That one print payload.txt: OK and e exit 0. If none of the names for the list dey present, --ignore-missing no go quietly succeed with zero files. E report say no file was verified and e exit non-zero. Na the behaviour you want, because a pass wey check nothing na failure wey you no go notice.

Publishers wey publish digest without make you read am by eye

To compare 64 hexadecimal characters by eye na where this habit dey fail badly. People dey check the first four characters and the last four, then call am match. Na exactly this kind comparison determined attacker dey plan for. Make the tool do the comparison instead. Set EXPECTED to the digest wey you copy from the publisher. Use EXPECTED= follow by the value wey you paste, then build the single line wey -c dey expect:

printf '%s  %s\n' "$EXPECTED" payload.txt > payload.sha256
cat payload.sha256
sha256sum -c payload.sha256

Two spaces dey between the digest and the file name. Na why the format string get two spaces. This na the format wey sha256sum dey write and wey -c dey parse. File wey hold digest and nothing else no be checksum line. So the check go reject the whole file with no properly formatted checksum lines found instead of guessing which file you mean. Some projects dey publish the BSD tagged format instead, SHA256 (payload.txt) = follow by the digest. GNU coreutils dey write this format with sha256sum --tag payload.txt and read am back with -c, so you fit save either format.

When check dey behave strangely, inspect the list itself with cat -A SHA256SUMS. E go mark the end of every line with $ and show characters wey you no fit see otherwise. Line wey end with ^M$ don pick carriage return from Windows editor. GNU sha256sum dey ignore that trailing character and still print OK. So CRLF list no be wetin dey break your check, although tools outside coreutils no dey as tolerant. Normalise the copy wey you keep with tr -d '\r' < SHA256SUMS > SHA256SUMS.clean.

Checksum prove wetin, and wetin e no prove?

Checksum prove one thing: the bytes for your disk na the same bytes wey produce the published digest. This completely cover accidental damage. E also cover careless attacker wey replace the file for download mirror but no fit change the page wey publish the digest.

E no prove who author the file. Digest na fact about bytes, e no be fact about people. If one page dey serve both the file and the digest, anybody wey fit change one fit change the other. Then your OK line only mean say the mirror agree with itself. So, na this rule make checksum worth running: collect the digest from different place from where you collect the file. For example, the project own domain over TLS (transport layer security), while the image come from mirror or torrent. Now attacker must control two places instead of one. E still no talk about wetin those verified bytes go do after you run dem. That one na separate question wey you suppose ask about anything wey go execute on your behalf, from install script to dsh plugin wey dey run with your agent permissions.

The algorithm matter too. SHA-256 (secure hash algorithm, 256-bit output) get no known collision as of August 2026, na why publishers dey use am. MD5 (message digest 5) and SHA-1 no hold up: people don fit construct two different files with the same MD5 digest since 2004, and dem publish chosen-prefix SHA-1 collision for 2020. An MD5SUMS file still dey catch truncated download, because random corruption no be crafted collision. E no fit stop person wey dey try deceive you. When project publish both, use the SHA-256 line.

Signature dey take over

Signature dey close the gap wey digest leave open. Publisher dey use private key sign the digest file, and you dey check am with their public key: gpg --verify SHA256SUMS.asc SHA256SUMS. If e pass, na person wey hold that key provide the list of digests. Then sha256sum -c SHA256SUMS go tie the file for your disk to the list, and the chain go run from the key reach the bytes.

The weak point don move go the key. If you fetch the key from the same page wey serve the file, attacker fit give you both parts. GnuPG dey clear about this, and first verification dey print Good signature together with WARNING: This key is not certified with a trusted signature!. Good signature mean say the mathematics correct. E no mean say the key belong to the project wey you get for mind. Get the fingerprint from another source, like the project documentation for different domain or distribution package wey don already ship the key, then compare the complete fingerprint instead of the last eight characters. Na the same care wey SSH private key deserve, for the same reason: the key na the trust decision, and everything wey follow inherit am.

Reproducible builds dey push this idea one step further. Published digest still tie you to binary wey one machine build. When project build reproducible, anybody fit compile the same source and get byte-identical output. This one allow independent builders confirm the published digest instead of asking you to trust wetin one server talk. This matter dey grow every year, as more code dey come through automated pipelines and machine-written patches. Deciding wetin you go accept into a build na policy question, and open source policies for AI-assisted code dey work on the same supply chain from the other end.

Your package manager dey do this one for you

For Debian and Ubuntu, apt dey run this whole chain every time you install something, without asking you. The package index get SHA-256 digest for each .deb file. The Release file get the digests for those index files, while InRelease get signature for Release. Dem dey check this signature against the keys inside /usr/share/keyrings and /etc/apt/trusted.gpg.d. When the chain break, apt go tell you: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY when third-party repository key no dey, or Hash Sum mismatch when the index wey you fetch no match the signed Release. Most times, this one mean say caching proxy serve stale file, or you catch mirror while e dey sync.

Na this standard you suppose use when project home page tell you to pipe script from curl straight into shell. Nothing verify the bytes, and you no even see the bytes. The server fit also return one thing to script and another thing to browser, and you no get any copy to inspect later. Download am to file with curl -fsSL <url> -o install.sh, hash am, read am with less, then run am only after that. This habit take about twenty seconds, and na the same habit wey you suppose start with a brand new VPS for the first ten minutes, before you install anything else for the box.

Keep digest list for wetin you install by hand

apt dey track packages wey you install. But e no dey track binary wey you copy enter /usr/local/bin, and nothing for the system dey watch am. Digest list go turn this into something wey you fit check anytime:

printf 'a second file\n' > notes.txt
sha256sum *.txt > inventory.sha256
sha256sum -c --quiet inventory.sha256

--quiet no go print anything when every file match. If some file no match, e go print only the lines wey fail. So, silence mean say check pass, and echo $? confirm am with 0. Na this form you suppose put for scheduled job. --status go further and no print anything at all; na only the exit status go remain. Point the same pattern to real files with sha256sum /usr/local/bin/* > ~/local-bin.sha256, and you get baseline. The list store paths exactly as you type dem, so absolute paths make the check work from any directory.

Make you understand wetin this baseline fit do. E fit detect file wey change. E no fit detect attacker wey don already get root, because that attacker fit rewrite inventory.sha256 as easily as e rewrite the binary. Keep the list outside the machine if you want am to get meaning. This na part of the bigger question of how much you really trust your VPS and who else fit reach the disk underneath am.

FAQ

Matching checksum mean say the download safe?

No. E mean say the bytes wey you get match the digest wey you compare dem against. If attacker control the page wey publish the digest, dem go publish the digest of their own file and your check go print OK. Match na consistency claim. Safety claim need signature wey you verify against a key wey you obtain from another source. Na only then the digest inherit that trust.

Why sha256sum -c dey print FAILED open or read?

Because e never read the file. A separate line just above am say No such file or directory with the name wey e dey find. The names inside SHA256SUMS file relative to the directory wey you run the command inside, so change go the directory wey hold the download and run am again. If the list also name files wey you no download, add --ignore-missing. Plain FAILED without open or read na the opposite situation: the file don read, and e digest no match.

MD5 good enough to verify download?

For damage wey happen by mistake, yes. Truncated transfer or bad disk block no go produce matching MD5 digest by chance. Against attacker, no. Dem don fit construct two different files with the same MD5 digest since 2004, and SHA-1 fall to chosen-prefix collision for 2020. Use the SHA-256 line when project publish both, and treat project wey only get MD5 as sign say the release process old.

Wetin be the difference between sha256sum -c and gpg --verify?

sha256sum -c prove say file match digest. gpg --verify prove say holder of particular private key sign the digest file. Dem answer different questions, so run both when project provide both. The signature make the digest list trustworthy, and the digest list then make the downloaded file trustworthy.

How I fit check one file against digest wey web page print?

No compare the characters by eye. Save the digest and file name for one line, with two spaces between dem, then run sha256sum -c against that file and read the OK or FAILED wey e print. Building the line with printf '%s %s\n' avoid formatting mistakes wey make sha256sum reject the file with no properly formatted checksum lines found.

#checksums#sha256sum#integrity#supply-chain#security