I recently had to deal with a bunch of Yubikeys. I wanted to reuse them for another purpose and therefore I wanted to factory reset them. This post won’t describe how to factory reset the whole Yubikey. Yubikeys have multiple parts, e.g. slot 1 and 2 and a Smart Card (PIV). During this post you can learn how to reset the Smart Card (PIV) and how to generate and flash a new OpenPGP key.

Factory reset

First, we will factory reset the Smart Card. There are for sure multiple ways to do this. In this post we will concentrate us on CLI standard tools. This should work on all Unix machines. The process how to factory reset was described on the GnuPG mailing list in this post.

Create a file with the following content:

 1/hex
 2scd serialno
 3scd apdu 00 20 00 81 08 40 40 40 40 40 40 40 40
 4scd apdu 00 20 00 81 08 40 40 40 40 40 40 40 40
 5scd apdu 00 20 00 81 08 40 40 40 40 40 40 40 40
 6scd apdu 00 20 00 81 08 40 40 40 40 40 40 40 40
 7scd apdu 00 20 00 83 08 40 40 40 40 40 40 40 40
 8scd apdu 00 20 00 83 08 40 40 40 40 40 40 40 40
 9scd apdu 00 20 00 83 08 40 40 40 40 40 40 40 40
10scd apdu 00 20 00 83 08 40 40 40 40 40 40 40 40
11scd apdu 00 e6 00 00
12scd apdu 00 44 00 00
13/echo card has been reset to factory defaults

And then use GnuPG to apply the above instructions to your connected Smart Card.

1$ gpg-connect-agent < file

Now reconnect the Yubikey.

 1$ gpg --card-status
 2Reader ...........: Yubico YubiKey OTP FIDO CCID
 3Application ID ...: D0000000000000000000000000000000
 4Application type .: OpenPGP
 5Version ..........: 3.4
 6Manufacturer .....: Yubico
 7Serial number ....: 12345678
 8Name of cardholder: [not set]
 9Language prefs ...: [not set]
10Salutation .......:
11URL of public key : [not set]
12Login data .......: [not set]
13Signature PIN ....: not forced
14Key attributes ...: rsa2048 rsa2048 rsa2048
15Max. PIN lengths .: 127 127 127
16PIN retry counter : 3 0 3
17Signature counter : 0
18KDF setting ......: off
19UIF setting ......: Sign=off Decrypt=off Auth=off
20Signature key ....: [none]
21Encryption key....: [none]
22Authentication key: [none]
23General key info..: [none]

Generate a new GnuPG key

While most GnuPG keys have a master key with capability certification and signing I rather recommend to create a master key with only certification.

Creating a master key with only certification means later we have to add a subkey for signing and encryption. Two benefits of this concept are:

  • We can only move the subkeys to the Yubikey and keep the master key offline. The Yubikey won’t be able to modify the key itself but only to sign and decrypt messages.
  • We can rotate the subkeys in the future and keep the master key. Our friends don’t have to learn a new key, they only need an update of the existing in their keyring.

Modify this command to your needs:

1$ gpg --batch --passphrase '123456' --default-new-key-algo rsa4096 --quick-gen-key "Alice <alice@example.com>" default cert 0
2gpg: revocation certificate stored as '/home/user/.gnupg/openpgp-revocs.d/D3ABF6D90F932570A1E1EB606836D82EED5B1BD3.rev'
3
4$ fpr="$(gpg --list-options show-only-fpr-mbox --list-secret-keys | awk '{print $1}')"
5$ gpg --list-secret-keys "$fpr"
6sec   rsa4096 2024-01-05 [C]
7      D3ABF6D90F932570A1E1EB606836D82EED5B1BD3
8uid           [ultimate] Alice <alice@example.com>

As shown above we have now a master key with capability certification. Now let’s add our subkeys.

1$ gpg --batch --pinentry-mode=loopback --passphrase '123456' --default-new-key-algo rsa4096 --quick-add-key $fpr default sign 1y
2$ gpg --batch --pinentry-mode=loopback --passphrase '123456' --default-new-key-algo rsa4096 --quick-add-key $fpr default encr 1y
3
4$ gpg --list-secret-keys
5sec   rsa4096 2024-01-05 [C]
6      D3ABF6D90F932570A1E1EB606836D82EED5B1BD3
7uid           [ultimate] Alice <alice@example.com>
8ssb   rsa4096 2024-01-05 [S] [expires: 2025-01-04]
9ssb   rsa4096 2024-01-05 [E] [expires: 2025-01-04]

Now we have our GnuPG key ready. Create a backup of this key and store it somewhere save offline!

$ gpg --armor --export-secret-keys "$fpr" > "${fpr}.asc"

Move GnuPG key to Smart Card

Now we have our (new) Yubikey and a fresh GnuPG key with a backup. Now let’s move the GnuPG subkeys to our Yubikey. During this process it will ask for two secrets. The first is the password of your GnuPG key, as you set it above. The second is the admin pin of the Yubikey. The Yubikey has two pins:

  • User pin: Is used to unlock the GnuPG key on the Yubikey and is used at each interaction. Defaults to 123456.
  • Admin pin: Is used while modifying the Smart Card or to unlock it and set a new user pin. Defaults to 12345678.
 1gpg --edit-key "$fpr"
 2Secret key is available.
 3
 4sec  rsa4096/0x6836D82EED5B1BD3
 5     created: 2024-01-05  expires: never       usage: C
 6     trust: ultimate      validity: ultimate
 7ssb  rsa4096/0xF249660366114098
 8     created: 2024-01-05  expires: 2025-01-04  usage: S
 9ssb  rsa4096/0x756D988D911A2AF8
10     created: 2024-01-05  expires: 2025-01-04  usage: E
11[ultimate] (1). Alice <alice@example.com>
12
13gpg> key 1
14
15sec  rsa4096/0x6836D82EED5B1BD3
16     created: 2024-01-05  expires: never       usage: C
17     trust: ultimate      validity: ultimate
18ssb* rsa4096/0xF249660366114098
19     created: 2024-01-05  expires: 2025-01-04  usage: S
20ssb  rsa4096/0x756D988D911A2AF8
21     created: 2024-01-05  expires: 2025-01-04  usage: E
22[ultimate] (1). Alice <alice@example.com>
23
24gpg> keytocard
25Please select where to store the key:
26   (1) Signature key
27   (3) Authentication key
28Your selection? 1
29
30sec  rsa4096/0x6836D82EED5B1BD3
31     created: 2024-01-05  expires: never       usage: C
32     trust: ultimate      validity: ultimate
33ssb* rsa4096/0xF249660366114098
34     created: 2024-01-05  expires: 2025-01-04  usage: S
35ssb  rsa4096/0x756D988D911A2AF8
36     created: 2024-01-05  expires: 2025-01-04  usage: E
37[ultimate] (1). Alice <alice@example.com>
38
39Note: the local copy of the secret key will only be deleted with "save".
40gpg> key 1
41
42sec  rsa4096/0x6836D82EED5B1BD3
43     created: 2024-01-05  expires: never       usage: C
44     trust: ultimate      validity: ultimate
45ssb  rsa4096/0xF249660366114098
46     created: 2024-01-05  expires: 2025-01-04  usage: S
47ssb  rsa4096/0x756D988D911A2AF8
48     created: 2024-01-05  expires: 2025-01-04  usage: E
49[ultimate] (1). Alice <alice@example.com>
50
51gpg> key 2
52
53sec  rsa4096/0x6836D82EED5B1BD3
54     created: 2024-01-05  expires: never       usage: C
55     trust: ultimate      validity: ultimate
56ssb  rsa4096/0xF249660366114098
57     created: 2024-01-05  expires: 2025-01-04  usage: S
58ssb* rsa4096/0x756D988D911A2AF8
59     created: 2024-01-05  expires: 2025-01-04  usage: E
60[ultimate] (1). Alice <alice@example.com>
61
62gpg> keytocard
63Please select where to store the key:
64   (2) Encryption key
65Your selection? 2
66
67sec  rsa4096/0x6836D82EED5B1BD3
68     created: 2024-01-05  expires: never       usage: C
69     trust: ultimate      validity: ultimate
70ssb  rsa4096/0xF249660366114098
71     created: 2024-01-05  expires: 2025-01-04  usage: S
72ssb* rsa4096/0x756D988D911A2AF8
73     created: 2024-01-05  expires: 2025-01-04  usage: E
74[ultimate] (1). Alice <alice@example.com>
75
76Note: the local copy of the secret key will only be deleted with "save".
77gpg> save
78
79$ gpg --list-secret-keys "$fpr"
80sec   rsa4096/0x6836D82EED5B1BD3 2024-01-05 [C]
81      Key fingerprint = D3AB F6D9 0F93 2570 A1E1  EB60 6836 D82E ED5B 1BD3
82uid                   [ultimate] Alice <alice@example.com>
83ssb>  rsa4096/0xF249660366114098 2024-01-05 [S] [expires: 2025-01-04]
84ssb>  rsa4096/0x756D988D911A2AF8 2024-01-05 [E] [expires: 2025-01-04]

You can now see that the subkeys are on a Smart Card (the lines are starting with ssb>) and not anymore stored on the computer.

The master key is still on the computer. As we have a backup of our master key we can now delete the master key from the computer too.

1$ gpg --export "$fpr" > "${fpr}.pub"
2
3$ gpg --delete-secret-keys "$fpr"
4
5sec  rsa4096/0x6836D82EED5B1BD3 2024-01-05 Alice <alice@example.com>
6
7Delete this key from the keyring? (y/N) y
8This is a secret key! - really delete? (y/N) y

Now get the key back from your Yubikey:

 1$ gpg --card-edit
 2
 3Reader ...........: Yubico YubiKey OTP FIDO CCID
 4Application ID ...: D0000000000000000000000000000000
 5Application type .: OpenPGP
 6Version ..........: 3.4
 7Manufacturer .....: Yubico
 8Serial number ....: 12345678
 9Name of cardholder: [not set]
10Language prefs ...: [not set]
11Salutation .......:
12URL of public key : [not set]
13Login data .......: [not set]
14Signature PIN ....: not forced
15Key attributes ...: rsa4096 rsa4096 rsa2048
16Max. PIN lengths .: 127 127 127
17PIN retry counter : 3 0 3
18Signature counter : 0
19KDF setting ......: off
20UIF setting ......: Sign=off Decrypt=off Auth=off
21Signature key ....: 25B9 6927 6D80 E187 8DB1  B5D9 F249 6603 6611 4098
22      created ....: 2024-01-05 00:00:00
23Encryption key....: 5FC2 A2F6 B9AA 86B8 4947  1432 756D 988D 911A 2AF8
24      created ....: 2024-01-05 00:00:00
25Authentication key: [none]
26General key info..:
27sub  rsa4096/0xF249660366114098 2024-01-05 Alice <alice@example.com>
28sec#  rsa4096/0x6836D82EED5B1BD3  created: 2024-01-05  expires: never
29ssb>  rsa4096/0xF249660366114098  created: 2024-01-05  expires: 2025-01-04
30                                  card-no: 0006 13062493
31ssb>  rsa4096/0x756D988D911A2AF8  created: 2024-01-05  expires: 2025-01-04
32                                  card-no: 0006 13062493
33
34gpg/card> fetch
35gpg: requesting key 0xF249660366114098 from hkps://keys.openpgp.org
36
37gpg/card> quit
38
39$ gpg --list-secret-keys "$fpr"
40sec#  rsa4096/0x6836D82EED5B1BD3 2024-01-05 [C]
41      Key fingerprint = D3AB F6D9 0F93 2570 A1E1  EB60 6836 D82E ED5B 1BD3
42uid                   [ultimate] Alice <alice@example.com>
43ssb>  rsa4096/0xF249660366114098 2024-01-05 [S] [expires: 2025-01-04]
44ssb>  rsa4096/0x756D988D911A2AF8 2024-01-05 [E] [expires: 2025-01-04]

Now the master key is not available anymore and the subkeys are only available on the Yubikey.

Don’t forget to edit your Yubikey to your needs. Set new pins and e.g. a name, a url where this key can be fetched from.

 1$ gpg --card-edit
 2[...]
 3
 4gpg/card> admin
 5Admin commands are allowed
 6
 7gpg/card> ?
 8quit           quit this menu
 9admin          show admin commands
10help           show this help
11list           list all available data
12name           change card holder's name
13url            change URL to retrieve key
14fetch          fetch the key specified in the card URL
15login          change the login name
16lang           change the language preferences
17salutation     change card holder's salutation
18cafpr          change a CA fingerprint
19forcesig       toggle the signature force PIN flag
20generate       generate new keys
21passwd         menu to change or unblock the PIN
22verify         verify the PIN and list all data
23unblock        unblock the PIN using a Reset Code
24factory-reset  destroy all keys and data
25kdf-setup      setup KDF for PIN authentication (on/single/off)
26key-attr       change the key attribute
27uif            change the User Interaction Flag
28openpgp        switch to the OpenPGP app