How to Check Download Checksum for Linux File
Use sha256sum to compare a file with SHA256SUMS, then change one byte and see the check fail. Learn what checksum fit prove, and wetin e no fit.
Verify download with checksum for 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 fit do both parts: by itself e dey print digest, and with -c e dey read list of digests and report which files match. This guide go run the whole 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 this 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 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 touch the rest of the system. Every command 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.txtYou go get 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 identical, 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
Digest wey show for screen no go help you next day. Write am go file, for format wey sha256sum itself dey write, so tool fit read am again later.
sha256sum payload.txt > SHA256SUMS
cat SHA256SUMS
sha256sum -c SHA256SUMSsha256sum -c dey read each line for the list, hash the file wey dem name for that line, then compare the two digests. If everything correct, e go print one line for each file:
payload.txt: OKCheck exit status too, because script dey read that one and e no dey read the text. echo $? dey print 0 after clean run. The name SHA256SUMS na convention, no be rule, but distributions and most release pages dey use am. So use am too, make the next person know wetin the file hold without opening am.
Flip one byte and watch the check fail
Now break the file on purpose. Dis na write one byte for offset 5 and leave everything else as e be, so the file go keep the same length and name.
printf 'X' | dd of=payload.txt bs=1 seek=5 conv=notrunc status=none
cat payload.txt
sha256sum -c SHA256SUMSconv=notrunc na the flag wey matter: if you no use am, dd go truncate the file for the point wey e stop writing, and you go dey test a damage type wey obvious pass. The check now go print:
payload.txt: FAILED
sha256sum: WARNING: 1 computed checksum did NOT matchecho $? go print 1. FAILED mean say the file don read, but e digest no match the one wey dey the list. Put the original bytes back and confirm say the check don return to OK:
printf 'the payload of a totally ordinary download\n' > payload.txt
sha256sum -c SHA256SUMSNa the whole habit be this. Difference of one byte anywhere for the file go produce FAILED. Download wey connection cut short, mirror wey serve yesterday build, proxy wey rewrite the file as e dey pass through, or disk wey return bad block: all of dem go show for that same line.
When the list names a file you no download
A real SHA256SUMS file from a distribution dey list every image wey the project releases, and you download one of dem. Reproduce that situation here.
printf 'a second file\n' > notes.txt
sha256sum payload.txt notes.txt > SHA256SUMS.all
rm notes.txt
sha256sum -c SHA256SUMS.allpayload.txt: OK
sha256sum: notes.txt: No such file or directory
notes.txt: FAILED open or read
sha256sum: WARNING: 1 listed file could not be readFAILED 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 compare. 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 wetin you actually get, ask for that:
sha256sum --ignore-missing -c SHA256SUMS.allThat one print payload.txt: OK and exit 0. If none of the names for the list dey present, --ignore-missing no go quietly succeed for zero files. E report say no file was verified and exit non-zero. Na the behaviour you want, because pass wey check nothing na the failure wey you no go notice.
Paste published digest without reading am by eye
Comparing 64 hexadecimal characters by eye na where this habit dey really fail. People dey check the first four characters and the last four, then call am match. Na exactly this kind comparison attacker wey plan well dey target. Make tool do the comparison instead. Set EXPECTED to the digest wey you copy from publisher. Use EXPECTED= follow by the value wey you paste, then build the single line wey -c expect:
printf '%s %s\n' "$EXPECTED" payload.txt > payload.sha256
cat payload.sha256
sha256sum -c payload.sha256Two spaces dey between the digest and the file name. Na why the format string get two spaces. Na this shape sha256sum dey write and na this shape -c dey parse. File wey hold digest and nothing else no be checksum line at all. So the check reject the whole file with no properly formatted checksum lines found instead of guessing which file you mean. Some projects publish BSD tagged style instead, SHA256 (payload.txt) = follow by the digest. GNU coreutils write this form with sha256sum --tag payload.txt and read am back with -c, so you fit save either shape.
When check dey behave strangely, inspect the list itself with cat -A SHA256SUMS. E 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 ignore that trailing character and still print OK. So CRLF list no be wetin dey break your check, although tools outside coreutils no dey tolerate am as much. 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 swap 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, not fact about people. If one page serve both the file and the digest, anybody wey fit change one fit change the other. For that case, your OK line only mean say the mirror agree with itself. So this na the rule wey make checksums worth running: collect the digest from somewhere different from where you collect the file. For example, take am from the project own domain over TLS (transport layer security), while the image come from a mirror or a torrent. Now attacker need control two places instead of one.
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 strong enough: people don construct two different files wey get the same MD5 digest since 2004, and dem publish chosen-prefix SHA-1 collision for 2020. An MD5SUMS file still 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.
When signature come in
Signature dey close the gap wey digest leave open. Publisher sign the digest file with private key, and you 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 connect the file for your disk to the list, and the chain 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 sides. 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 a distribution package wey already ship the key, then compare the complete fingerprint instead of the last eight characters. This na the same care wey SSH private key deserve, for the same reason: na the key be the trust decision, and everything wey follow inherit am.
Reproducible builds carry this idea one step further. Published digest still tie you to a binary wey one machine build. When project build dey reproducible, anybody fit compile the same source and get byte-identical output, so independent builders fit confirm the published digest instead of asking you to trust wetin one server talk. This matter more every year, as more code dey come through automated pipelines and machine-written patches. To decide 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 for you
For Debian and Ubuntu, apt dey run this chain every time you install something, without anybody asking am. The package index get SHA-256 digest for each .deb file. The Release file get the digests for those index files, and InRelease get signature over Release. Dem dey check am against the keys for /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 dey missing, or Hash Sum mismatch when the index wey you fetch no match the signed Release. Most times, this mean say caching proxy serve stale file, or you catch mirror while e dey sync.
Na this standard you suppose use measure am when project home page tell you pipe script from curl straight enter shell. Nothing verify the bytes, and you no even see dem. The server fit also return one thing to script and another thing to browser, and you no get copy to inspect later. Download am enter file with curl -fsSL <url> -o install.sh, hash am, read am with less, and run am only after that. This habit go cost about twenty seconds, and na the same habit wey make sense to start with new VPS for the first ten minutes, before you install anything else for the box.
Keep list of digests for wetin you install by hand
apt dey track packages wey you install. E no track binary wey you copy go /usr/local/bin, and nothing for the system dey monitor am. Digest list go give you 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 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 you go get. Point the same pattern at real files with sha256sum /usr/local/bin/* > ~/local-bin.sha256 and you don get baseline. The list store paths exactly as you type dem, so absolute paths make the check work from any directory.
Make sure say you understand wetin this baseline fit do. E fit detect file wey change. E no fit detect attacker wey 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 mean anything. 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, e fit publish the digest of e own file, and your check go print OK. Match na consistency claim. To claim say file safe, you need signature wey you verify against key wey you obtain from another source. Na only then the digest go inherit that trust.
Why sha256sum -c dey print FAILED open or read?
Because e never read the file. Separate line just above am talk say No such file or directory, with the name wey e dey look for. The names inside SHA256SUMS file dey relative to the directory wey you run the command inside. So enter the directory wey hold the download, then run am again. If the list still name files wey you no download, add --ignore-missing. Plain FAILED without open or read na the opposite situation: the file don read, but e digest no match.
MD5 good enough to verify download?
For accidental damage, yes. Truncated transfer or bad disk block no go produce matching MD5 digest by chance. Against attacker, no. People don fit construct two different files with the same MD5 digest since 2004, and SHA-1 suffer chosen-prefix collision for 2020. Use the SHA-256 line when project publish both, and see MD5-only project as sign of old release process.
Wetin be the difference between sha256sum -c and gpg --verify?
sha256sum -c prove say file match a 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' dey prevent formatting mistakes wey make sha256sum reject the file with no properly formatted checksum lines found.