19

Is there a way to tell GPG, that if it needs to decrypt something, that it can find the private encryption key on one of two smart cards?

My (simplified) setup is as follows:

  • Generated a master key offline with an encryption subkey.
  • Transferred the encryption subkey to Yubikey 1.
  • On Yubikey 1, generated auth and sign subkeys.
  • Transferred the encryption subkey to Yubikey 2.
  • On Yubikey 2, generated auth and sign subkeys.

So I am left with:

gpg2 --list-keys
/Users/scott/.gnupg/pubring.gpg
-------------------------------
pub   3072R/600955C7 2016-09-09
uid       [ultimate] Scott Cariss 
uid       [ultimate] Scott Cariss (msn.com) 
uid       [ultimate] Scott Cariss (bigfish.co.uk)
uid       [ultimate] [jpeg image of size 12378]
sub   2048R/6FE6415F 2016-09-09
sub   2048R/D6DBBCAC 2016-09-09
sub   2048R/01A208C9 2016-09-09
sub   2048R/8D2A1368 2016-10-23
sub   2048R/65B08C5B 2016-10-23

My encryption subkey is shared between smart cards and have individual auth and sign keys on each smart card.

But when I come to decrypt something it always goes to the first smart card and won't find the encryption key on the other smart card. The gpg-agent/pin entry will just ask me to insert the correct smart card.


UPDATE (Workaround)

As already answered, it is not something that GPG supports but I have found a working solution that works for me.

On Mac OS X I use https://www.controlplaneapp.com/ to detect the arrival of one of my smart cards (yubikeys) and get it to run a script:

#!/bin/bash
{
    killall -9 ssh-agent gpg-agent
    for keystub in $(/usr/local/MacGPG2/bin/gpg2 --with-keygrip --list-secret-keys {{EMAIL ADDRESS}} | grep Keygrip | awk '{print $3}'); do rm /Users/{{USERNAME}}/.gnupg/private-keys-v1.d/$keystub.key; done;
    /usr/local/MacGPG2/bin/gpg2 --card-status
    eval $(/usr/local/MacGPG2/bin/gpgconf --launch gpg-agent)
    ssh-add -l
} &> /Users/{{USERNAME}}/bin/gpg-card-change-log.txt

exit 0

As the secret keys are all kept offline, there is no harm in deleting them and then running --card-status which brings in the secret key stubs from the smart card currently plugged in.

3
  • 2
    I have tested the above snippet with gpg 2.1.x and 2.2.x, and unfortunately invoking gpg2 --batch --delete-secret-keys {{KEY_ID}} doesn't do much. What one needs to do is invoke gpg --with-keygrip --list-secret-keys {{KEY_ID}}, get the keygrip values for the subkeys moved to the card, and then delete or rename the corresponding files from ~/.gnupg/private-keys-v1.d/. Consider this oneliner: for keystub in $(gpg --with-keygrip --list-secret-keys 0xB1349B0B4B8B7600 | grep Keygrip | awk '{print $3}'); do ls -la ~/.gnupg/private-keys-v1.d/$keystub.key; done; it's ugly, but it works. Dec 13, 2017 at 7:17
  • Thanks Rouben, when I upgraded to >= 2.1 the delete secret keys no longer worked. I have since upgraded my script to incorporate your comment. I will update my question with my new workaround.
    – Scott
    Jan 16, 2018 at 13:36
  • I ran into exactly the same problem and since I use several yubikeys I have written a script that lets you select a key and automatically removes the key stubs (I took some steps to make sure the script is quite safe to run). See: github.com/rjekker/gpg-switch-card
    – rje
    Jan 10, 2019 at 22:58

3 Answers 3

11

I guess you will have bad luck, and this is not supported by GnuPG. When using OpenPGP smart cards, a secret key dummy is stored in your keyring, holding a reference to the smart card it is stored on. The secret key subpacket looks like this when displayed through gpg --list-packets:

:secret sub key packet:
        version 4, algo 1, created 1358985314, expires 0
        pkey[0]: [2048 bits]
        pkey[1]: [17 bits]
        gnu-divert-to-card S2K, algo: 0, simple checksum, hash: 0
        serial-number:  01 23 45 67 89 ab cd ef 01 23 45 67 89 ab cd ef
        keyid: 9FF7E53ACB4BD3EE

Peeking at the code, it does not seem to me more than one serial number would be supported.

6
  • Would it at all be possible to change this value by a script? I already have a script that restarts the GPG agent when any of my Yubikeys are inserted or ejected.
    – Scott
    Mar 27, 2017 at 16:44
  • Looks like this has been requested to be fixed bugs.gnupg.org/gnupg/issue1798 but not currently being worked on. It seems by the original poster that a workaround is to delete the stub on insert of the card
    – Scott
    Mar 27, 2017 at 16:52
  • At least with the old .gpg keyrings consisting of plain uncompressed OpenPGP packets, this should be possible by simply replacing the serial number. Be aware those are binary files, so look for solutions considering binary replacement. And better create lots of backups when fiddling with the private keyring...
    – Jens Erat
    Mar 27, 2017 at 18:27
  • 3
    @Brady Thanks for sharing the GnuPG bug report! FYI, the GPG bug report you originally brought up on Mar 27 has been merged into this bug report, which is active. The proposal now seems to augment the private key stub storage format to allow for multiple SmartCard serial numbers to be stored, which sounds promising. For the time being, see my prior comment to your question above. Dec 13, 2017 at 7:25
  • 1
    It looks on the active thread like this may be solved, anybody has a simple to follow explanation / example?
    – Zorglub29
    May 28, 2020 at 20:18
5

Running

gpg-connect-agent "scd serialno" "learn --force" /bye

will update the secret key stubs for the PGP keys on the currently inserted key. So running that after key insertion will cause gpg to use the currently inserted key.

Create backup Yubikey with identical PGP keys

1
  • Works perfectly and this is exactly what I was looking for! Thank you very much. May 13, 2022 at 7:24
-1
resetcard() {
  rm -rf ~/.gnupg/private-keys-v1.d
  killall -9 ssh-agent gpg-agent
}

I found out if you delete this cached folder (im not 100% sure what it is for, but i think it must be some sort of key cache??) and then restart the agent it works just fine afterward. Wish we didn't have to do this

1
  • Aren't you suggesting to delete all private keys someone has stored?
    – chpio
    Jul 11, 2022 at 10:03

You must log in to answer this question.

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