12

I tried to use gpg --delete-secret-keys to delete some revoked subkeys but ended up accidentally deleting my primary key instead.

I was able to reproduce my mistake with the following commands:

$ gpg --batch --passphrase '' --quick-generate-key 'test key' rsa4096 cert 0
gpg: key 0xA52099E0E7EB77A5 marked as ultimately trusted
gpg: revocation certificate stored as '~/.gnupg/openpgp-revocs.d/D7D79C32883EA862C586881DA52099E0E7EB77A5.rev'
$ gpg --batch --passphrase '' --quick-add-key D7D79C32883EA862C586881DA52099E0E7EB77A5 rsa4096 sign 0
$ gpg --list-keys
pub   rsa4096/0xA52099E0E7EB77A5 2019-04-10 [C]
      Key fingerprint = D7D7 9C32 883E A862 C586  881D A520 99E0 E7EB 77A5
uid                   [ultimate] test key
sub   rsa4096/0x20AA2F4F7A28CD01 2019-04-10 [S]
      Key fingerprint = 9CAE 802D A78E 4624 BD8F  88FE 20AA 2F4F 7A28 CD01
$ gpg --delete-secret-keys 9CAE802DA78E4624BD8F88FE20AA2F4F7A28CD01

sec  rsa4096/0xA52099E0E7EB77A5 2019-04-10 test key

Delete this key from the keyring? (y/N)

Even though I specified the subkey by fingerprint, gpg asks me to confirm the deletion of the primary key.

The manual states:

--delete-secret-keys name

Remove key from the secret keyring. In batch mode the key must be specified by fingerprint. The option --yes can be used to advice gpg-agent not to request a confirmation. This extra pre-caution is done because gpg can’t be sure that the secret key (as controlled by gpg-agent) is only used for the given OpenPGP public key.

I tried using batch mode as well:

$ gpg --batch --yes --delete-secret-keys 9CAE802DA78E4624BD8F88FE20AA2F4F7A28CD01
$ gpg --list-secret-keys
# Empty output.
# Primary key has been deleted.

I specified the subkey by fingerprint but gpg interpreted the command as if I had specified my primary key instead.

What is the correct way to do this? Did I understand it wrong?

4
  • Thanks! This is a great question. It is very odd behavior how GPG removes all the subkeys.
    – xer0x
    Commented Oct 4, 2022 at 5:32
  • 1
    @xer0x You're welcome. It should be fixed in newer versions of GPG! Commented Oct 4, 2022 at 17:13
  • 1
    Unfortunately, I just came across this behaviour today with gpg 2.4.3. It deleted the primary secret key (and all subkeys). It's not fixed, @MatheusMoreira. Looks like we need to end the key id with !, which is quite unintuitive. Commented Oct 23, 2023 at 10:35
  • @BenButterworth That is true indeed!! It is absolutely necessary to append ! to the fingerprint in order to operate only on that exact subkey! To this day I'm still prone to forgetting about that! I have no idea why this thing is so hard to use! Just for the record, the second answer o this question mentions this! Commented May 22 at 15:25

2 Answers 2

10

As explained by Peter Lebbing and Daniel Kahn Gillmor on the mailing list, the answer for gpg 2.2.15 is to ask gpg-agent to delete the secret subkey.

# Obtain the keygrip of the subkey you want to delete.
$ gpg --with-keygrip --list-secret-keys "$YOUR_FINGERRINT"

# Ask gpg-agent to delete the key for you.
# There should be a graphical confirmation prompt.
$ gpg-connect-agent "delete_key $KEYGRIP" /bye

gpg-agent is the program that actually manages the secret keys. Each secret key corresponds to a file named "$GNUPGHOME"/private-keys-v1.d/"$KEYGRIP".key. In order to delete a secret subkey, the user must obtain its keygrip and then ask gpg-agent to delete it.

Documentation for the delete_key command:

$ gpg-connect-agent 'help delete_key' /bye
# DELETE_KEY [--force|--stub-only] <hexstring_with_keygrip>
#
# Delete a secret key from the key store.  If --force is used
# and a loopback pinentry is allowed, the agent will not ask
# the user for confirmation.  If --stub-only is used the key will
# only be deleted if it is a reference to a token.
OK

Apparently, there is no way to tell gpg to ask gpg-agent to delete a secret subkey on the user's behalf. An issue has been opened about this.

1
  • 2
    Note that this doesn't necessarily ensure that the key cannot be forensically recovered.
    – forest
    Commented Apr 12, 2019 at 6:34
7

As of gpg 2.2.19 (maybe earlier versions too) --delete-secret-keys (and --delete-keys, --delete-secret-and-public-key) works as expected and deletes only a subkey if the fingerprint of the subkey suffixed by an exclamation mark is given.

From the man:

--delete-keys name

Remove key from the public keyring. In batch mode either --yes is required or the key must be specified by fingerprint. This is a safeguard against accidental deletion of multiple keys. If the exclamation mark syntax is used with the fingerprint of a subkey only that subkey is deleted; if the exclamation mark is used with the fingerprint of the primary key the entire public key is deleted.

Example

$ gpg --list-keys --with-subkey-fingerprints test
pub   rsa4096 2022-01-18 [SC] [expires: 2024-01-18]
      9D41A3F0A1A83972A9CC66FA4D37F47018B8C1B9
uid           [ultimate] test key
sub   rsa2048 2022-01-18 [E]
      BC147C4DF05144EDF10E9C76B0A369B86587C7CF
sub   rsa2048 2022-01-18 [S]
      D4BF3307C15BFBB146D62A4D8E43F32CE9A59953
           
$ gpg --delete-secret-and-public-keys BC147C4DF05144EDF10E9C76B0A369B86587C7CF!
gpg (GnuPG) 2.2.19; Copyright (C) 2019 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.


sec  rsa2048/B0A369B86587C7CF 2022-01-18 test key

Note: Only the secret part of the shown subkey will be deleted.

Delete this key from the keyring? (y/N) y
This is a secret key! - really delete? (y/N) y

sub  rsa2048/B0A369B86587C7CF 2022-01-18 test key

Note: Only the shown public subkey will be deleted.

Delete this key from the keyring? (y/N) y

$ gpg --list-keys --with-subkey-fingerprints test
pub   rsa4096 2022-01-18 [SC] [expires: 2024-01-18]
      9D41A3F0A1A83972A9CC66FA4D37F47018B8C1B9
uid           [ultimate] test key
sub   rsa2048 2022-01-18 [S]
      D4BF3307C15BFBB146D62A4D8E43F32CE9A59953
1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .