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.

Subkey or whole identity?If only a signing subkey was exposed, revoke that subkey and add a new one, keeping the identity everyone trusts. If the primary key was exposed or lost without a backup, revoke the whole identity using the primary or the stored revocation certificate.Which secret was exposed?signing subkey onlyRevoke the subkeyidentity survivesprimary keyRevoke identitypublish, start overprimary lost, not leakedRevoke identityuse stored certificatean offline primary turns most incidents into the left-hand branch

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.

Where the revocation must goForges hold an uploaded copy that must be replaced or removed. Keyservers distribute the key to anyone who fetches it. Teammates and CI keep copies in their own keyrings. Project trust files and release documentation pin the key for users.Forgesre-upload or deleteKeyserverssend revoked keyKeyringsteammates and CIPinned copiestrust files, docsmiss one and that verifier keeps saying the key is fine
# 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
How a revocation reaches a verifierThe owner attaches a revocation to the key and uploads it to the forge and a keyserver. A CI gate refreshes its pinned keyring from the repository, sees the revocation, and starts rejecting signatures from the revoked subkey.ownerforgekeyserverCI gateupload revoked keysend-keyscommit pinned keystatus R on old sigsa verifier only knows about a revocation once its copy of the key carries it

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.