Verify a download before you run it
Every setup guide says to check the signature and then moves on. This is the part they skip: the three files, the three commands, and the alarming warning that appears when everything has in fact gone right.
Wallet software is the one thing in self-custody you install from the internet before you have any way to tell whether it is genuine. Supply chain and vendor risk covers what verification proves and where the chain runs out. This page is the missing half: how to actually do it, and how to read the output, which is where most people quietly give up.
It takes about ten minutes the first time and under a minute afterwards. Do it once per download, on every machine that will run the software.
1What this defends against, precisely
Being specific here matters, because verification is often sold as a general-purpose safety ritual and it is not one.
- A substituted download. A hostile mirror, a compromised CDN, a corrupted transfer, a file altered in flight.
- The wrong site entirely. Fake wallet sites buy search ads and rank above the real project. A file from an impostor site will not verify against the real project's key.
- A tampered update. Particularly worth it for wallets that have historically had fake update prompts pushed at users from inside the application.
- It does not tell you the software is safe. It tells you the project published it.
- It does not defeat a dishonest maintainer. Someone entitled to sign releases can sign a bad one, and it will verify perfectly.
- It does not help if you got the key from the same page as a fake download. That is the loop this page's last section is about.
2Why there are three files, not two
Almost every serious Bitcoin project publishes the same three things, and the shape only makes sense once you see what each one is for.
| File | Looks like | What it is for |
|---|---|---|
| The release | Sparrow-2.5.4.msi | The thing you actually want to run. |
| A checksum manifest | manifest.txt, SHA256SUMS | A list of filenames and their SHA-256 hashes. |
| A signature over the manifest | manifest.txt.asc, SHA256SUMS.asc | Proof the manifest came from the project. |
The indirection is the clever part. Signing every installer separately would be tedious, so the project signs one small text file listing the hashes of all of them. Verify the signature on that list, then check your download against the list, and you have transitively verified your download. Two links in a chain.
This is also why a checksum published on its own proves much less. A hash tells you the file arrived intact. Only a signature tells you who published the hash.
3The three commands
You need GnuPG. On macOS it comes with GPG Suite or brew install gnupg; on Linux it is gpg in every package manager; on Windows it ships with Gpg4win.
The pattern is always the same three steps, whatever the project. Sparrow's own published instructions look like this — substitute the version you actually downloaded, and use whatever filenames your vendor publishes.
- Import the signing key.
curl https://keybase.io/craigraw/pgp_keys.asc | gpg --import - Verify the manifest's signature.
gpg --verify sparrow-2.5.4-manifest.txt.asc - Check your file against the manifest.
shasum -a 256 --ignore-missing --check sparrow-2.5.4-manifest.txton macOS, orsha256sum --ignore-missing --check sparrow-2.5.4-manifest.txton Linux.
Step three should print your filename followed by OK. The --ignore-missing flag matters: the manifest lists every platform's build, and without it the command complains loudly about the dozen files you did not download.
All three must pass. Any one of them alone proves very little — a signature check without the hash check tells you the project signed some list, and a hash check without the signature check tells you your file matches a list that anyone could have written.
A laptop screen photographed slightly off-axis in a dim room, a terminal showing a completed gpg verification: the Good signature line and the capitalised WARNING about the key not being certified both legible in the same frame.
Image to come
4The warning that means everything worked
This is the step that stops people, and nothing on the download page prepares them for it. A completely successful verification prints something like this:
gpg: Good signature from "Craig Raw <craig@sparrowwallet.com>" [unknown]gpg: WARNING: This key is not certified with a trusted signature!gpg: There is no indication that the signature belongs to the owner.Primary key fingerprint: D4D0 D320 2FC0 6849 A257 B38D E946 1833 4C67 4B40
Read in order, that looks like a pass followed by a failure. It is not. The first line is the verification result and it says the signature is valid. The warning underneath is answering a completely different question.
GnuPG maintains a web of trust — a record of whose keys you have personally vouched for. You have not vouched for this key, because you imported it thirty seconds ago from a URL. So GnuPG tells you, correctly, that it has no independent basis for believing the key belongs to the person named in it. That warning will appear every time until you explicitly sign the key locally, and essentially nobody does.
What to actually look for
Good signature is the pass. BAD signature is the failure, and it is unambiguous when it happens — it does not hide in a warning. If you see BAD, delete the download and start again from a freshly typed address; do not retry the same file.
5The fingerprint is the part you actually verify
Given the warning above, the honest question is what the signature check is worth at all. The answer is that it is worth exactly as much as your confidence in the fingerprint — and that is a thing you can work on.
The fingerprint on the last line is the key's identity. Confirming it is the whole of the trust decision, and the useful moves are these:
- Compare it against a second, independent source. The project's GitHub, its documentation, a release announcement, an archived copy of the page. A fake site can serve you a fake key; serving you a fake key that also matches four other places is a much larger job.
- Fetch it over a different network. A phone on mobile data rather than the same wifi is a cheap and surprisingly effective check.
- Prefer a key you have used before. A fingerprint you verified two years ago and have checked against every release since is far stronger evidence than one you fetched five minutes ago. Keep your keyring rather than re-importing each time.
- Write the fingerprint down. Once, in your notes, next to the project name. Then future releases are a comparison rather than a fresh act of faith.
6One signer, or many
Sparrow is signed by one person. Bitcoin Core is not, and the difference is worth understanding because it is a genuinely stronger model.
Bitcoin Core's SHA256SUMS.asc carries signatures from a number of independent developers, each of whom built the release themselves from source and got the same bytes. Verifying it produces a run of separate results rather than one, and the project's guidance is to import keys from several people you find trustworthy rather than relying on any single one.
What that buys is a defence the single-signer model cannot offer: one compromised developer machine, or one coerced maintainer, does not silently produce a valid release. It also demonstrates the reproducibility claim rather than asserting it — independent people compiling the same source and arriving at identical binaries is the evidence.
So a single Good signature line on a multi-signer project is a partial result. Check that enough of the signers are keys you meant to trust.
7When there is only a checksum
Some things are published with a hash and nothing else. Be exact about what that can do: it catches a truncated download, a proxy that rewrote something, a failing USB stick. It cannot catch an adversary, because the checksum is served from the same place as the file it describes, and anyone able to replace one can replace the other. Same-origin checksums catch accidents, not attackers.
Where it matters, get a second copy of the expected hash from somewhere the same server does not control. A repository's commit history, a build log, or a mirror will do. Then compare the two.
Build provenance, which is a different thing
A checksum on its own says nothing about where a file came from. It says only whether your copy matches the digest you were handed. A signed build attestation is different in kind: it is a signature over the file's digest, recording which repository, which workflow and which source ref produced those exact bytes, and it is verified against a signer identity rather than against a number on the same page. That is the gap between the two paragraphs above and this one.
This site's own offline Workshop file has both. The SHA-256 sits beside it, and the repository's workflow also mints a keyless attestation over the downloadable bytes whenever they change. If you have GitHub's CLI:
- The short form checks that some attestation from that repository covers these bytes:
gh attestation verify entropy-offline.html -R HodlDee/selfcustody - The form worth using also pins which workflow and which branch signed it:
gh attestation verify entropy-offline.html -R HodlDee/selfcustody --signer-workflow HodlDee/selfcustody/.github/workflows/build.yml --source-ref refs/heads/main - If either reports no matching attestation, the file may predate this repository being renamed. An attestation records the identity as it stood when it was signed, so the owner has to change in both arguments, not just the first:
gh attestation verify entropy-offline.html -R DeesNeez/selfcustody --signer-workflow DeesNeez/selfcustody/.github/workflows/build.yml --source-ref refs/heads/main - One of the two has to pass. A name mismatch by itself is not evidence of tampering, and it is not permission to run the file either. If neither identity verifies, you have an unverified file, and the right response is to download it again from the published location rather than to decide it is probably fine.
- The two commands do not prove the same thing, which is why both are here. A repository name on its own does not say which workflow produced the file. Any workflow in that repository able to mint an attestation would satisfy it, so a compromised or newly added one would pass.
--signer-workflowand--source-refpin the answer to the build this project actually publishes from. They are the difference between "something in that repository" and "that build, on main". - Keep the three checks separate in your head. A matching hash establishes that your copy agrees with the digest you were given. If that digest came from the same server as the file, it establishes nothing else, which is the whole point of the section above. A signature or an attestation additionally ties those bytes to a signer you can name. None of the three says the software is any good, that the source it was built from is trustworthy, or that the repository was not compromised before the build ran.
- An attestation covers bytes, not versions. It says these exact bytes came from that build. It does not say they are the current release, or that a later one does not fix something.
The Workshop guide makes the same points about its own file, and this project's SECURITY.md carries the full procedure. A project talking honestly about its own checksums is the standard to hold others to.
8Windows without a terminal
Windows has no sha256sum, and its built-in tool prints the hash rather than checking it for you:
CertUtil -hashfile Sparrow-2.5.4.msi SHA256prints the file's hash.- Open the manifest in Notepad, find the line for your filename, and compare the two strings.
- Compare the whole string, not the ends. Checking the first and last few characters is the one shortcut that an attacker can actually plan around.
For the signature step, Gpg4win installs the same gpg --verify command, and Kleopatra offers it through a window if you would rather not use a terminal at all.
The short version
Download three files, not one. Verify the signature on the checksum list, then check your file against the list, and require both to pass. Expect the not-certified warning and do not read it as a failure — Good signature is the result, BAD signature is the failure. Then spend your attention where it actually counts, which is deciding that the fingerprint belongs to the project, and keeping that key so every later release is a comparison instead of a leap.
If you take one thing from this page
Verification answers one narrow question — did this file come from the same key as the last one — and answers it very well. It cannot tell you the project deserves your trust. Keep the two questions separate, and read what a signature cannot prove before deciding how much weight to put on a green line in a terminal.
Commands and filenames follow the projects' own published instructions and change between releases; substitute the version you downloaded and prefer the vendor's current page over this one. The multi-signer description reflects Bitcoin Core's documented release process, where checksums are signed by a number of independent builders.