What does PGP signature verification in Gradle's dependency verification feature actually verify, and how does it differ from a checksum?
answer
- checksum = integrity only
- PGP = integrity + authenticity
- .asc detached signature
- private signs / public verifies
- fallback to checksum when no .asc
basics
~10 sPGP verification checks that a dependency's .asc signature file was produced by a trusted publisher's private key, proving authenticity. A checksum only proves the bytes match a recorded hash, not who produced them.
solid answer
~50 sGradle dependency verification supports two mechanisms recorded in `verification-metadata.xml`: checksums and PGP signatures. A **checksum** (sha256, etc.) only confirms the artifact's bytes equal a value you trust — it proves integrity but says nothing about *who* published it; if an attacker swaps both the artifact and your recorded checksum, you'd never know. **PGP** verifies a detached signature file (the artifact's `.asc`) against the publisher's public key. Because only the holder of the private key can produce a valid signature, a passing check proves both integrity *and* authenticity — the bytes came from someone holding the trusted key. In practice you list `<trusted-keys>` (by long key ID/fingerprint) and Gradle downloads each `.asc`, fetches the public key from a key server or local keyring, and validates the signature. Artifacts without a `.asc` fall back to checksum verification.
code
xml · 6 lines<configuration>
<verify-signatures>true</verify-signatures>
</configuration>
<trusted-keys>
<trusted-key id="ABCDEF0123456789ABCDEF0123456789ABCDEF01" group="com.example"/>
</trusted-keys>go deeper
Know the one-line distinction: checksum = integrity, PGP = integrity + authenticity via a .asc signature and a trusted public key.
Explain the .asc detached signature, public/private key roles, and the checksum fallback when no signature is published.
Discuss trust scoping (group/module), key sourcing (key server vs keyring), and why both mechanisms coexist in one metadata file.
Frame PGP within a supply-chain threat model: what attacks it stops vs. doesn't (e.g. trusting a malicious key), and org policy for which keys are trusted.
## What problem this solves When Gradle resolves a dependency it downloads a binary (a JAR, POM, etc.) from a repository. **Dependency verification** lets you assert, ahead of time, that every artifact you consume is exactly what you expect — defending against a compromised mirror, a hijacked account, or a man-in-the-middle swapping bytes. Gradle records these expectations in a file at `gradle/verification-metadata.xml`. There are two complementary mechanisms: ### Checksums A checksum is a cryptographic hash (e.g. `sha256`) of the artifact's bytes. You record the expected value; Gradle recomputes the hash on download and fails if it differs. This proves **integrity** (the bytes were not altered) but not **authenticity** — a hash carries no notion of an author. If an attacker can alter the artifact *and* the recorded hash (e.g. by compromising the same supply chain), the check passes. ### PGP signatures PGP (Pretty Good Privacy) uses asymmetric cryptography. A publisher signs the artifact with their **private key**, producing a small detached signature file published alongside the artifact with a `.asc` extension (e.g. `foo-1.0.jar.asc`). Anyone can verify that signature using the publisher's **public key**: a valid signature could only have been produced by the private-key holder, so it proves **both integrity and authenticity**. In `verification-metadata.xml` you express trust in keys: ```xml <configuration> <verify-metadata>true</verify-metadata> <verify-signatures>true</verify-signatures> </configuration> <trusted-keys> <trusted-key id="ABCDEF0123456789ABCDEF0123456789ABCDEF01" group="com.example"/> </trusted-keys> ``` When `verify-signatures` is true, for each artifact Gradle: 1. Downloads the artifact's `.asc` detached signature (if the repository publishes one). 2. Obtains the signing public key — from a configured **key server** (e.g. `keyserver.ubuntu.com`) or a **local keyring** file (`gradle/verification-keyring.keys` / `.gpg`). 3. Validates the signature; if it's made by a `<trusted-key>` (matched by fingerprint, optionally scoped to a `group`/`module`), the artifact passes. Artifacts that have **no** `.asc` published can't be PGP-verified, so Gradle falls back to the recorded checksum for those. This is why real-world metadata files contain a mix of `<pgp>` and `<sha256>` entries. ### Key identifiers Keys are referenced by their **fingerprint** (40 hex chars) or **long key ID** (last 16 hex). Always prefer the full fingerprint: short key IDs are vulnerable to collision attacks where an attacker crafts a different key with the same short ID. ### Bottom line Use PGP where publishers sign (most Maven Central artifacts do), and checksums everywhere else. PGP raises the bar from "these bytes match what I saw" to "these bytes were signed by a party I chose to trust."
- If an artifact has no .asc file published, what happens under signature verification?Gradle cannot PGP-verify it and falls back to the recorded checksum for that artifact, so the metadata file ends up mixing <pgp> and <sha256> entries.
- Why prefer a full fingerprint over a short/long key ID in <trusted-key>?Short key IDs (and to a lesser extent long IDs) are susceptible to collision attacks where an attacker forges a different key sharing the same ID. The 40-char fingerprint is collision-resistant.
A checksum is like comparing a parcel against a photo of the contents — right contents, but anyone could have sent it. A PGP signature is a tamper-evident wax seal stamped with a signet ring only the sender owns: it proves both the contents and the sender.
saying these in an interview costs you the question
- Claiming a checksum proves who published an artifact (it only proves integrity).
- Saying PGP verification re-hashes the artifact like a checksum — it validates an asymmetric signature instead.