Revoking a GPG key and publishing the revocation Jump to heading
Revoking a GPG key is two separate acts that people tend to treat as one. The first is creating the revocation: a signed statement, attached to the key, saying it should no longer be trusted. The second is getting that statement to everyone who verifies with the key. A revocation that exists only in your own keyring protects nobody — every forge, CI runner and colleague still holds the unrevoked copy and keeps reporting good signatures. This page covers both acts: revoking the right thing with the right reason, and publishing it everywhere it needs to go. It sits within protecting and rotating signing keys.
When to use this approach Jump to heading
- A signing subkey or a whole GPG identity has been, or may have been, compromised.
- You are retiring an identity permanently — leaving a project, changing employer, or moving to SSH signing.
- You lost the primary key and need to use the pre-made revocation certificate.
- For SSH keys, revocation works differently: you close the key’s window in the trust file, as described in rotating a compromised commit-signing key.
Step 1 — Decide what to revoke: a subkey or the whole identity Jump to heading
Revoke the smallest thing that addresses the problem. If a laptop holding only a signing subkey was stolen, revoke that subkey; the primary was never on the laptop, so the identity is intact. If the primary itself leaked, the whole identity must go.
Step 2 — Revoke a single subkey Jump to heading
Subkey revocation needs the primary secret key, so this is one of the occasions to bring it out of offline storage, as in keeping a GPG primary key offline.
export GNUPGHOME=$(mktemp -d)
gpg --import /media/offline/secret-primary-and-subkeys.asc
gpg --edit-key "$PRIMARY_FPR"
# gpg> key 1 # select the compromised subkey (an asterisk marks it)
# gpg> revkey
# Reason: 1 = Key has been compromised
# gpg> addkey # add the replacement signing subkey while you are here
# gpg> save
gpg --armor --export "$PRIMARY_FPR" > public-with-revoked-subkey.asc The reason code matters to verifiers. “Compromised” tells software to distrust signatures made at any time; “superseded” and “no longer used” tell it that signatures made before the revocation date are still good. Choose honestly — claiming “superseded” for a stolen key would leave forged signatures trusted.
# Verification: the subkey shows as revoked
gpg --list-keys --with-colons "$PRIMARY_FPR" | awk -F: '$1=="sub"{print $5, $2}' # 'r' marks revoked Step 3 — Revoke a whole identity Jump to heading
With the primary available, generate a fresh revocation. Without it, use the certificate you created at key generation.
# With the primary available
gpg --output revoke.asc --gen-revoke "$PRIMARY_FPR"
gpg --import revoke.asc
# Without the primary: import the stored certificate on any machine holding the public key
gpg --import /media/offline/revoke-$PRIMARY_FPR.asc
gpg --armor --export "$PRIMARY_FPR" > public-revoked.asc # Verification: the primary is marked revoked
gpg --list-keys "$PRIMARY_FPR" | head -2 # shows [revoked: YYYY-MM-DD] ⚠️ SAFETY WARNING: Revoking a whole identity cannot be undone. Once a revoked key reaches a keyserver or a forge, it stays revoked there permanently, and every signature it ever made may be reported as untrustworthy depending on the reason code. Confirm you are revoking the right fingerprint — compare the full forty-character fingerprint, not the short ID — before publishing.
Step 4 — Publish the revocation everywhere the key lives Jump to heading
Revocation only works once verifiers receive it. List every place the public key was published, then update each one.
# Forge: replace the uploaded key with the revoked version (or delete it)
gh gpg-key list
gh api -X DELETE "/user/gpg_keys/$GPG_KEY_ID"
gh gpg-key add public-with-revoked-subkey.asc # for a subkey revocation only
# Keyserver, if the key was ever published there
gpg --keyserver hkps://keys.openpgp.org --send-keys "$PRIMARY_FPR"
# Repository-pinned copies used by CI gates
cp public-with-revoked-subkey.asc trust/maintainers/alice.asc
git commit -am "Revoke compromised signing subkey for alice" && git push Deleting the key from a forge account makes every past commit it signed display as unverified there. Re-uploading the key with the revoked subkey keeps other subkeys’ commits verified. Choose based on what the incident requires.
Step 5 — Tell people and check that verifiers noticed Jump to heading
Post a short notice where your team or users will see it: the full fingerprint, what was revoked, the reason, the date, and the replacement key’s fingerprint. Then confirm that the verifiers you control have actually picked up the revocation.
# A CI runner using the pinned keyring should now reject signatures from the revoked subkey
git log -1 --format='%G? %GK' "$SUSPECT_COMMIT" # expect R (revoked) or not G Validation checklist Jump to heading
Frequently Asked Questions Jump to heading
Will revoking my key make all my old commits show as unverified? Jump to heading
It depends on the reason code and the verifier. With “compromised”, most tools treat every signature as suspect. With “superseded” or “no longer used”, well-behaved tools keep trusting signatures made before the revocation date. Forges vary, and some show any revoked key’s signatures as unverified regardless.
I lost the revocation certificate and the primary. What now? Jump to heading
You cannot revoke the key. Remove it from every forge account and pinned keyring you control, publish a signed statement from your new key explaining that the old one is abandoned, and let its expiry date finish the job. This is the strongest argument for setting an expiry on every primary.
Do I need to revoke the key if I am just switching to SSH signing? Jump to heading
Not urgently. Revoke with reason “no longer used” so verifiers know not to expect new signatures, and keep it published so historical commits still verify. There is no reason to make old signatures look suspect.
Related Jump to heading
- Protecting & Rotating Signing Keys — the parent topic.
- Rotating a Compromised Commit-Signing Key — the incident runbook around this step.
- Keeping a GPG Primary Key Offline — where the revocation certificate is stored.
- Signing Commits with X.509 Certificates — where revocation is handled by a CA instead.