skip to content

useInMemoryPgpKeys has a two-argument form and a form that also takes a key id. Why does the key-id overload exist, and when do you need it?

level: middleimportance: should knowfreq 30%

answer

  1. armored export = master + subkeys
  2. 2-arg = default/first key
  3. keyId overload selects a subkey
  4. dedicated signing subkey [S]
  5. public key must be on a keyserver

basics

~20 s

An armored export can contain a master key plus several subkeys. The 2-arg form uses the first/default key; the keyId overload lets you pick a specific (sub)key by id when more than one is present.

solid answer

~40 s

`useInMemoryPgpKeys(secretKey, password)` takes the armored secret-key block and assumes there is one usable signing key to apply. But a PGP secret-key export often bundles a **master key plus one or more subkeys** (commonly a dedicated signing subkey). When that block has multiple keys, Gradle needs to know which one to sign with. `useInMemoryPgpKeys(keyId, secretKey, password)` adds an explicit **key id** (the short or long hex id of the desired subkey) so the right key is selected deterministically. You typically need it when you exported a master key together with subkeys and want to sign with a specific signing subkey, or when ambiguity would otherwise pick the wrong key. If your export contains exactly one signing key, the 2-arg form is sufficient.

code

kotlin · 7 lines
kotlin
signing {
    val keyId = System.getenv("SIGNING_KEY_ID")        // the signing subkey's hex id
    val key   = System.getenv("SIGNING_KEY")           // armored bundle (master + subkeys)
    val pass  = System.getenv("SIGNING_PASSWORD")
    useInMemoryPgpKeys(keyId, key, pass)
    sign(publishing.publications)
}

go deeper

for a junior

Recall that a key id can be passed to disambiguate which key signs; the simple 2-arg form exists too.

for a middle

Explain master-key-plus-subkeys bundles and why the keyId overload picks the right signing subkey deterministically.

for a senior

Discuss offline-master + signing-subkey hygiene and ensuring the published public key matches the signing key Central validates against.

for a principal

Address key architecture and rotation policy: dedicated rotatable signing subkeys, keeping masters offline, and consistent keyId wiring across pipelines.

## PGP keys are not always singular A real-world PGP secret key is frequently a **key bundle**: a primary (master) key used for certification, plus one or more **subkeys** for specific capabilities — encryption, authentication, and **signing**. A best practice is to keep the master key offline and use a dedicated signing **subkey** for day-to-day signing. When you run `gpg --armor --export-secret-keys`, the resulting armored block can therefore contain *several* keys. ## What the overloads do - `useInMemoryPgpKeys(secretKey, password)` — Gradle parses the armored block and uses its default/first secret key. Fine when the block holds a single signing key. - `useInMemoryPgpKeys(keyId, secretKey, password)` — you additionally pass a **key id** (the hex identifier of a specific subkey, e.g. the last 8 or 16 hex digits of its fingerprint). Gradle then selects exactly that key for signing. Why the id form matters: if the armored bundle contains multiple secret keys and you rely on the 2-arg form, Gradle may pick a key that isn't the intended signing key (or one Maven Central won't validate against the public key you uploaded to the keyserver). The id form removes that ambiguity. ## Finding the right key id ```bash gpg --list-secret-keys --keyid-format LONG # sec rsa4096/AAAA1111BBBB2222 ... <- master # ssb rsa4096/CCCC3333DDDD4444 ... <- signing subkey [S] ``` Use the subkey marked with the signing capability `[S]` as the `keyId`. ## Practical guidance - **One key in the export** → 2-arg form is simplest. - **Master + subkeys exported together** → use the keyId overload and pass the signing subkey's id. - Make sure the **public** counterpart of whatever key you sign with has been published to a keyserver, or Maven Central validation will fail even though the signature is technically valid. ```kotlin signing { useInMemoryPgpKeys( System.getenv("SIGNING_KEY_ID"), // e.g. CCCC3333DDDD4444 System.getenv("SIGNING_KEY"), // armored bundle System.getenv("SIGNING_PASSWORD"), ) sign(publishing.publications) } ```

  • Where do you find the key id to pass to the overload?
    Run gpg --list-secret-keys --keyid-format LONG and use the hex id of the subkey marked with the signing capability [S].
  • If your armored export contains only one signing key, do you need the keyId overload?
    No — the 2-arg useInMemoryPgpKeys(secretKey, password) is sufficient when there's a single unambiguous signing key.

saying these in an interview costs you the question

  • Thinking the keyId is a passphrase or fingerprint of the public certificate only.
  • Assuming every armored export contains exactly one key.
  • Forgetting that the matching public key must be published for downstream validation.

context