Downloading software from the internet always carries some risk. A man-in-the-middle attacker, a compromised mirror server, or a malicious package maintainer could substitute a backdoored binary for the real thing. PGP signature verification gives you a cryptographic guarantee that the file you downloaded was signed by the expected key. and that it hasn’t been altered in transit.
This guide walks through the full verification workflow using GnuPG on Linux, macOS, and Windows.
What PGP Signature Verification Actually Checks
When a developer releases software, they typically:
- Build the binary or archive
- Generate a hash of that file (SHA-256, SHA-512, etc.)
- Sign that hash with their private key
- Publish the
.sigor.ascsignature file alongside the download
When you verify the signature, GPG checks two things: that the signature was produced by the claimed key, and that the file matches what was signed. If either fails, the verification fails.
What it does not check is whether the signing key itself belongs to who you think it does. That requires importing and trusting the correct key first.
Installing GnuPG
Linux
Debian/Ubuntu
sudo apt install gnupg
Fedora/RHEL
sudo dnf install gnupg2
Arch
sudo pacman -S gnupg
macOS
brew install gnupg
Windows
Download Gpg4win from https://gpg4win.org/. it includes Kleopatra, a GUI frontend, and the gpg command-line tool.
Step 1 - Obtain the Developer’s Public Key
You need the correct public key before you can verify anything. Sources in order of trustworthiness:
From a project’s official website (most common):
Tor Project key
curl https://dist.torproject.org/torbrowser/openpgp/signed-keyring.gpg | gpg --import
From a keyserver (use fingerprint, never just name/email):
gpg --keyserver keys.openpgp.org --recv-keys 0x4E2C6E8793298290
From a file posted on the project site:
gpg --import developer-key.asc
After importing, verify the fingerprint matches what the project publishes:
gpg --fingerprint 0x4E2C6E8793298290
The fingerprint must be verified out-of-band. check the project’s official site, their GitHub profile, or a signed announcement. Never trust a keyserver fingerprint alone.
Step 2 - Download the Software and Signature File
You need both the file you want to verify and its signature. The signature file typically has the same name with .sig or .asc appended:
wget https://example-project.org/downloads/app-2.0.tar.gz
wget https://example-project.org/downloads/app-2.0.tar.gz.sig
Some projects publish a checksums file that is itself signed:
wget https://example-project.org/downloads/SHA256SUMS
wget https://example-project.org/downloads/SHA256SUMS.gpg
Step 3 - Verify the Signature
Direct signature on the file
gpg --verify app-2.0.tar.gz.sig app-2.0.tar.gz
A successful verification looks like this:
gpg: Signature made Fri 14 Mar 2026 12:04:19 UTC
gpg: using RSA key 4E2C6E8793298290
gpg: Good signature from "Alice Developer <alice@example-project.org>" [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 - A490 D0F4 D311 A412 3456 789A 4E2C 6E87 9329 8290
The “Good signature” line is what matters. The warning about trust is expected unless you’ve explicitly set a trust level for that key.
Signed checksums file
First verify the checksums file itself
gpg --verify SHA256SUMS.gpg SHA256SUMS
Then check the file hash against the verified checksums
sha256sum --check --ignore-missing SHA256SUMS
Both commands must succeed. The second check confirms the downloaded binary matches the hash that was signed.
Reading the Output Correctly
Good signature. the file was signed by the key and hasn’t been altered:
gpg: Good signature from "Alice Developer <alice@example-project.org>"
BAD signature. the file does not match what was signed. Stop immediately, discard the file, and report it to the project:
gpg: BAD signature from "Alice Developer <alice@example-project.org>"
No public key. you haven’t imported the signing key yet:
gpg: Can't check signature: No public key
Key expired. the key has an expiry date that has passed. Check whether the project has published a new key:
gpg: Note - This key has expired!
Setting Key Trust Level
The “key not certified” warning appears because GPG doesn’t automatically trust imported keys. If you’ve verified the fingerprint through multiple channels and are confident the key is legitimate, you can set a trust level:
gpg --edit-key 4E2C6E8793298290
Inside the interactive prompt:
gpg> trust
Your decision? 4
(4 = I trust this key fully)
gpg> quit
Future verifications against this key will no longer show the trust warning.
Automating Verification in Scripts
For package management scripts or CI pipelines, automate signature verification with a non-interactive check:
#!/bin/bash
set -euo pipefail
FILE="app-2.0.tar.gz"
SIG="app-2.0.tar.gz.sig"
EXPECTED_KEY="4E2C6E8793298290"
Import key if not present
gpg --list-keys "$EXPECTED_KEY" >/dev/null 2>&1 || \
gpg --keyserver keys.openpgp.org --recv-keys "$EXPECTED_KEY"
Verify
if gpg --verify "$SIG" "$FILE" 2>&1 | grep -q "Good signature"; then
echo "Verification passed: $FILE"
else
echo "VERIFICATION FAILED: $FILE. aborting"
exit 1
fi
Common Projects and Their Verification Methods
| Project | Key source | Signature format |
|---|---|---|
| Tor Browser | dist.torproject.org | .asc direct |
| Tails OS | tails.boum.org | OpenPGP signed checksums |
| VeraCrypt | veracrypt.fr | .sig direct |
| GnuPG itself | gnupg.org | .sig direct |
| Debian ISOs | debian.org/CD/verify | SHA512SUMS.sign |
What Verification Cannot Protect Against
Signature verification confirms authenticity. it does not guarantee the software is safe. A legitimate key can sign malware if the developer’s system is compromised, if the project has been acquired, or if the developer intentionally includes malicious code. Verification establishes origin; it cannot establish intent.
For high-stakes software, cross-reference release announcements, check reproducible build attestations where available, and monitor the project’s security disclosure history.
Frequently Asked Questions
How long does it take to verify pgp signatures on software downloads?
For a straightforward setup, expect 30 minutes to 2 hours depending on your familiarity with the tools involved. Complex configurations with custom requirements may take longer. Having your credentials and environment ready before starting saves significant time.
What are the most common mistakes to avoid?
The most frequent issues are skipping prerequisite steps, using outdated package versions, and not reading error messages carefully. Follow the steps in order, verify each one works before moving on, and check the official documentation if something behaves unexpectedly.
Do I need prior experience to follow this guide?
Basic familiarity with the relevant tools and command line is helpful but not strictly required. Each step is explained with context. If you get stuck, the official documentation for each tool covers fundamentals that may fill in knowledge gaps.
Can I adapt this for a different tech stack?
Yes, the underlying concepts transfer to other stacks, though the specific implementation details will differ. Look for equivalent libraries and patterns in your target stack. The architecture and workflow design remain similar even when the syntax changes.
Where can I get help if I run into issues?
Start with the official documentation for each tool mentioned. Stack Overflow and GitHub Issues are good next steps for specific error messages. Community forums and Discord servers for the relevant tools often have active members who can help with setup problems.
Related Articles
- How to Verify Software Supply Chain Integrity
- PGP Email Encryption Setup Guide 2026
- How To Set Up Pgp Encrypted Email In Thunderbird Step
- How to Use GPG Signed Emails to Verify Sender Identity
- Syncthing Setup Guide for Private File Sync
- AI Coding Assistant Session Data Lifecycle Built by theluckystrike. More at zovo.one