skip to content

What does verifying a detached GPG .asc signature on a release tarball actually prove?

level: juniorimportance: must knowfreq 62%

answer

  1. integrity plus origin, nothing more
  2. origin is relative to a key
  3. the key is the whole question
  4. 'Good signature' can still print [unknown]
  5. custody at signing time, not build integrity

basics

~20 s

It proves the file is byte-for-byte what the holder of that private key signed. It does not prove the key belongs to the project, that the build was clean, or that the code is safe.

solid answer

~40 s

A detached signature is a separate `.asc` file holding a signature over the artifact's digest, so the artifact itself is untouched. `gpg --verify project-1.4.2.tar.gz.asc project-1.4.2.tar.gz` recomputes that digest and checks it against a public key already in your keyring. That proves exactly two things: the file has not changed since it was signed, and it was signed by whoever holds that private key. Nothing else. gpg prints `Good signature` and exits zero even when the key is marked `[unknown]`, so if you fetched the key from the same page as the download, a compromised site just serves you a matching pair. And a signature attests custody of a key at signing time, not build integrity: a maintainer whose machine is compromised signs a backdoored tarball with a perfectly valid signature.

code

bash · 8 lines
bash
$ gpg --verify project-1.4.2.tar.gz.asc project-1.4.2.tar.gz
gpg: Signature made Tue 04 Mar 11:02:13 CET
gpg:                using RSA key A1B2C3D4...
gpg: Good signature from "Release Manager <[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.
$ echo $?
0

go deeper

for a junior

Be ready to state the two claims out loud: the file is unchanged since signing, and it was signed by the holder of that key. Then name one thing it does not prove.

for a middle

Explain the mechanics: signature over a digest, key looked up in the local keyring, verification fully offline. Know that a good signature from an untrusted key still exits zero.

for a senior

Show how you turn this into a gate that means something: pin the accepted fingerprint, build the keyring from reviewed material, verify the signed checksum file before any hash comparison.

for a principal

Be able to argue what the control is worth across an estate: publishing signatures nobody verifies buys nothing, so the investment case is about verification coverage, not signing coverage.

## What a detached signature is An OpenPGP **detached signature** is a small separate file, conventionally `<artifact>.asc` when ASCII-armored (`.sig` when binary), containing a signature made with a private key over a digest of the artifact's bytes. *Detached* means the artifact is left alone: the tarball you download is byte-identical to the one the publisher produced, and the signature travels beside it. That is why release engineering likes the format — mirrors, CDNs and web servers serve both as ordinary blobs, tooling that does not care about signatures is unaffected, and the signature can be added or replaced without rewriting the artifact. Verification is a local, offline operation: 1. gpg reads the signature file and learns which key ID made it. 2. It looks that key up **in your local keyring**. If it is not there, verification cannot complete. 3. It recomputes the digest of the artifact and checks the signature over that digest under the key's public half. ## The two claims it makes - **Integrity.** One flipped byte in the tarball and the digest changes, so the signature fails. This holds against a hostile mirror, a truncated download, or a proxy that rewrites content. - **Origin relative to a key.** The signature could only have been produced by the holder of that private key. That second claim is the one people over-read. It is *relative to a key*, not to a project, a person or an organisation. Verification answers "was this signed by key `0xAB…`?" It does not answer "is key `0xAB…` the project's key?" — that question is not cryptography, it is key discovery and trust, and it has to be solved on some other channel. ## The `[unknown]` trap GnuPG happily reports a **good signature from an untrusted key**. You get `Good signature from "Release Manager <[email protected]>" [unknown]` followed by `WARNING: This key is not certified with a trusted signature!` — and the process exits zero. A verification step in a script that only checks the exit status therefore passes on a key an attacker uploaded thirty seconds ago. Any real verification gate has to pin *which* key is acceptable (by full fingerprint), not merely assert that some signature validated. ## Three things it does not prove - **That the build is clean.** Signing happens after the artifact exists. It says a key-holder vouched for these bytes, not that they were built from the published source, on a trusted builder, without injected code. Claims about how an artifact came to be are provenance, carried in a separate attestation, not in a signature. - **That the code is free of vulnerabilities.** A perfectly signed release can ship a decade-old flaw. Signing and vulnerability management are orthogonal controls. - **That the signer intended to endorse this build.** A key stolen from a laptop, or held in CI secrets a workflow can read, signs whatever it is pointed at. ## Checksums are not a substitute Many projects publish `SHA256SUMS` next to the artifacts. Comparing a hash against that file proves only that the server served two mutually consistent files — anyone who could alter the tarball could alter the list. The pattern that works is `SHA256SUMS.asc`: one signature covering the whole checksum file, so you verify the signature once and can then check any number of artifacts cheaply against hashes you now have reason to believe. The ordering matters: verify the `.asc` **before** trusting any hash inside. ## Where this lands in practice A long-running open-source project publishes a source tarball, a detached `.asc`, and a `KEYS` file, and the files are served from volunteer mirrors it does not control. The signature is genuinely valuable there: it is what stops a mirror operator from serving altered source. But the value is realised only by consumers who actually verify, against a key they obtained on a channel independent of the mirror. In many projects the count of those consumers is roughly one — a downstream distribution packager — after which the code flows unverified to thousands of machines through the distribution's own signing. Publishing trust material and having anyone check it are two different achievements, and only the second changes an attacker's job. So the honest one-line summary is: a detached signature makes tampering *evident to whoever checks*, given that they already know the right key. Everything hard about the control lives in those last two clauses.

  • A project ships SHA256SUMS and SHA256SUMS.asc rather than a signature per artifact. Why, and what is the verification order?
    One signature covers the whole list, so publishers sign once and consumers verify once, then check any number of artifacts by hash. The order is fixed: verify `SHA256SUMS.asc` against a key you trust first, then compare hashes. Reversed, the checksum file is just data served by the same host as the artifact, and proves nothing about origin.
  • Your CI verification step runs gpg --verify and gates on the exit status. What is wrong with that?
    gpg exits zero for a good signature from any key in the keyring, including one an attacker planted or one auto-fetched during verification. The gate has to assert the signer's full fingerprint against an allowed list, ideally with a keyring built from a pinned, reviewed key file rather than whatever the keyring happens to contain.
  • If a signature does not cover the build, what would you add to cover it?
    A provenance attestation from the builder: a signed statement naming the artifact by digest and describing how it was produced — source repository and commit, build entry point, builder identity. That is a different document with a different signer, and it answers "how did this come to be", where the release signature answers "who vouches for these bytes".

A wax seal proves the letter was sealed with a particular ring and has not been opened since. It tells you nothing about whether that ring is the king's, or whether the letter is true.

saying these in an interview costs you the question

  • Says a valid signature means the code is safe
  • Treats a checksum from the same page as equivalent to a signature
  • Assumes gpg exits non-zero when the key is untrusted
  • Claims the signature covers how the artifact was built
  • Cannot say where the verifying key came from

context