Verifying PGP Signatures: A Step-by-Step Guide

Learn how to verify OpenPGP and GPG digital signatures step-by-step. Discover cryptographic mechanics, key fingerprint audits, and hardened workflows.

On this page

Digital signatures provide cryptographic proof of authenticity, integrity, and non-repudiation. In high-threat environments—such as investigative journalism, source protection, software supply chain auditing, and vulnerability disclosure—verifying a Pretty Good Privacy (OpenPGP) signature is not merely an optional best practice; it is the fundamental barrier preventing man-in-the-middle (MitM) tampering and identity spoofing. A digital signature guarantees that a given file, message, or commit was created by the holder of a specific private key and that the signed data has not been altered by even a single bit in transit.

The Cryptographic Anatomy of an OpenPGP Signature

To audit signatures properly, one must understand what happens beneath the interface of tools like GnuPG (gpg) or Sequoia PGP (sq). An OpenPGP signature (standardized under RFC 4880 and updated in RFC 9580) does not encrypt the content; rather, it binds an identity to an exact payload through asymmetric cryptography and cryptographic hash functions.

Hashing and Asymmetric Operations

The signing process executes the following steps:

  1. The signing software takes an arbitrary payload (binary file, plain text, or git object) and calculates a cryptographic digest using a collision-resistant hash function (e.g., SHA-256, SHA-512).
  2. The calculated digest, along with metadata packets specified by OpenPGP (such as the signature creation timestamp, preferred algorithms, and signer key ID), is formatted into a signature packet.
  3. The signer's private key (using RSA, Ed25519, or ECDSA) computes a mathematical signature over this digest structure.

During verification, the recipient computes the hash of the received document using the exact algorithm declared in the signature packet. The recipient then uses the signer's public key to verify that the mathematical signature corresponds precisely to the computed digest. If even one byte of the document was altered, the resulting hash will mismatch, causing verification to fail.

Signature Formats: Detached, Cleartext, and Inline

OpenPGP implementations generally produce and consume three primary formats of signatures:

  • Detached Signatures (.sig, .asc): The cryptographic signature is held in a distinct, separate file. The original payload remains entirely untouched. This format is standard for software distributions (e.g., Linux kernel tarballs, Tails images, Tor Browser binaries) because users can execute the installer without needing to extract it from an OpenPGP container.
  • Cleartext Signatures: The payload (strictly UTF-8 plain text) is wrapped inside an OpenPGP framing structure, delimited by -----BEGIN PGP SIGNED MESSAGE----- and -----BEGIN PGP SIGNATURE-----. The text remains human-readable without PGP tooling, though it is subject to canonicalization rules regarding line breaks and whitespace.
  • Inline/Opaque Signatures: The payload and the signature are bundled into a single binary or ASCII-armored file. Extracting the payload requires passing the archive through OpenPGP software.

Prerequisites: Key Acquisition and the Authenticity Dilemma

The security of signature verification rests entirely on one premise: you must be certain that the public key you are using actually belongs to the purported author. Verifying a signature against an unauthenticated public key proves mathematical consistency, but it does not prove identity. If an attacker intercepts your traffic and replaces both the software artifact and the signature with ones generated by their own key, a naive verification will succeed.

Obtaining the Public Key

Never rely solely on legacy public keyservers without additional validation. Modern workflows retrieve keys through authenticated out-of-band channels:

  • Web Key Directory (WKD): An HTTPS-based lookup protocol where domain administrators serve public keys for their domain over https://openpgpkey.example.org/.well-known/openpgpkey/....
  • Project Git Repositories: Developer keys committed to audited repositories, provided the commit history itself is signed and authenticated.
  • In-Person or Out-of-Band Fingerprint Exchange: Comparing fingerprints over authenticated voice channels, Signal messages with verified safety numbers, or physical business cards.

To fetch a key using GnuPG via WKD:

gpg --locate-keys [email protected]

To import a manually retrieved public key file:

gpg --import developer_key.asc

The Danger of Short and Long Key IDs

Legacy systems frequently referenced keys using short (8-character hex, 32-bit) or long (16-character hex, 64-bit) Key IDs. Do not use 32-bit or 64-bit Key IDs for identity verification. Short Key IDs can be trivial to duplicate using basic hash collisions on consumer hardware; even 64-bit collisions have been generated by determined researchers. You must inspect the complete 40-character hexadecimal fingerprint (or modern 64-character V5 fingerprints):

gpg --fingerprint [email protected]

Ensure that every character matches the cryptographic fingerprint published across the developer's verified communication channels.

Step-by-Step Verification Workflows

Verifying Detached Signatures

When downloading software releases, you typically obtain the payload (e.g., software-1.0.tar.gz) and a signature file (e.g., software-1.0.tar.gz.asc or .sig). Both files must reside in the same directory.

Run the verification command by passing the signature file first, followed by the data file:

gpg --verify software-1.0.tar.gz.asc software-1.0.tar.gz

If the signature file retains its original name paired to the payload (for instance, archive.tar.gz.sig and archive.tar.gz), GnuPG will automatically infer the payload name if you pass only the signature file:

gpg --verify software-1.0.tar.gz.sig

Verifying Cleartext Signatures

Cleartext signatures are common in security advisories, signed emails, and plain text manifests. Because the payload and signature reside in the same document, specify only that file:

gpg --verify security-advisory.txt.asc

Interpreting GnuPG Status Outputs

GnuPG writes signature verification outputs to standard error (stderr). A successful output appears as follows:

gpg: Signature made Wed 15 May 2024 10:24:00 AM UTC
gpg:                using EDDSA key 9A3B5C7D8E1F2A3B4C5D6E7F8A9B0C1D2E3F4A5B
gpg: Good signature from "Developer Name <[email protected]>" [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: 9A3B 5C7D 8E1F 2A3B 4C5D  6E7F 8A9B 0C1D 2E3F 4A5B

Analyze these lines carefully:

  • Good signature: This indicates mathematical validity. The payload is guaranteed not to have been modified since the signature was applied, and it was signed by the specific private key corresponding to the listed fingerprint.
  • BAD signature: The document has been modified, corrupted, or signed with an incompatible key. Discard the associated payload immediately.
  • The WARNING: This key is not certified notice: This does not mean the signature failed. It simply means your local GnuPG trust database (the Web of Trust) has not been configured to trust this key as an introducer of other keys, or you have not marked this key as locally validated. As long as you manually compared the Primary key fingerprint against an authentic source, the signature is cryptographically valid.

Establishing Trust: Local Certification and the Web of Trust

To eliminate the persistent "WARNING: This key is not certified" prompt and allow your system to programmatically validate files in automated pipelines, you must explicitly certify the key using your own local keypair.

Once you have validated the full fingerprint out-of-band, execute:

gpg --quick-lsign-key "9A3B5C7D8E1F2A3B4C5D6E7F8A9B0C1D2E3F4A5B"

The --quick-lsign-key command creates a local signature (type 0x10) that certifies the key in your local keyring without exporting that signature to external keyservers, protecting your social graph from public exposure.

Alternatively, open the interactive key editor:

gpg --edit-key "9A3B5C7D8E1F2A3B4C5D6E7F8A9B0C1D2E3F4A5B"
gpg> trust
Your decision? 5 (I trust ultimately - reserved for personal keys) or 4 (I trust fully)
gpg> save

Hardening Verification Workflows against Modern Attacks

High-security verification routines must account for advanced attack vectors, including hash collisions, algorithm downgrades, and automation parser vulnerabilities.

Deprecating Weak Digests

Legacy signatures created with SHA-1 are cryptographically vulnerable. Practical chosen-prefix collision attacks against SHA-1 exist (e.g., the SHAttered and SHA-1 Chosen-Prefix attacks). Enforce strong digest minimums by placing the following directives in your ~/.gnupg/gpg.conf file:

# Reject weak digest algorithms
weak-digest SHA1
weak-digest RIPEMD160

# Force modern preferences for operations
personal-digest-preferences SHA512 SHA384 SHA256
cert-digest-algo SHA512

Cleartext Normalization and MIME Pitfalls

Cleartext signatures are inherently fragile. RFC 4880 specifies that trailing spaces on lines must be stripped before hashing, and line endings must be canonicalized to CRLF (\r\n). Email clients and text editors that automatically convert character sets, strip tabs, or re-wrap paragraphs frequently invalidate mathematically valid cleartext signatures. When transmitting critical information, prefer detached signatures or binary inline signatures over cleartext armor.

Automating Verification Responsibly

Do not verify signatures in automated scripts by parsing standard output or checking text strings like grep "Good signature". Attackers can inject crafted User ID strings containing the words "Good signature" into a malicious key. Instead, rely strictly on GnuPG's exit codes or use machine-readable status descriptors:

# Proper script verification via exit code
if gpg --verify release.tar.gz.asc release.tar.gz >/dev/null 2>&1; then
    echo "Verification succeeded."
else
    echo "Verification failed! Halting pipeline." >&2
    exit 1
fi

For mission-critical production pipelines, utilize --status-fd 1 and parse explicit OpenPGP status tokens like [GNUPG:] NEWSIG, [GNUPG:] BADSIG, and [GNUPG:] VALIDSIG.

Verification as an Operational Habit

In secure computing, unverified data is untrusted data. Whether validating an operating system image, importing an administrative patch, or reviewing an investigative lead from an anonymous source, signature verification bridges the gap between transmission channels and cryptographic truth. Establishing a systematic, hardened verification routine protects you against supply chain compromises and ensures that your tools remain authentic down to the very last byte.

Keywords
PGP signature verificationGnuPG verifyOpenPGPcryptographic integritydetached signatureskey fingerprintsupply chain security