Setup of YubiKey PGP module

GPG YubiKey

Intro

This post is about how I set up PGP module on my YubiKeys. It is not a comprehensive guide. For more complete guide I refer you to Dr Duh1 guide HERE. My entire GPG/Yubikey setup is built based on it. I read it and I tweaked it only slightly.

This article is in some sense covers part of its content, but in a specific scenario. The scenario is that user want to create a prepare a new YubiKey when the GPG keys are already created. The article assume you store keys the way Dr Duh recommends. If you haven’t followed his/her comprehensive guide, probably it is better to start there first.

Context

GPG is one of a very few tools I use daily. When setup properly it can increase security and convenience of use. While it has entire spectrum of use cases, I use it for a few, possibly not the first things that come up to mind when you think GPG:

  • to encrypt some files I store in the cloud,
  • to encrypt project related secrets with pass (very handy in scripting, e.g. for injecting secrets directly to env variables when starting process),
  • to use GPG identity to authenticate via SSH,
  • to sign commits.

In my GPG setup I have a one master key and three sub-keys. Technically, one master key is enough to do all you need, but by leveraging sub-keys we split concerns - master represents identity, sub-keys are workers - they do all the job: authentication, signing, decryption. That way I know that no matter what happens, master, the identity key is safe. It is probably more relevant for people who exchange their keys with others, e.g. to communicate securely, still I’m trying to mimic their practices and keep my identity key protected.

The easiest way to keep the master secure is to keep it offline, on a USB stick, some SDcard, as a printout of hex or a QRcode. Yep, you can do all that if you like. You can printout you private key and keep the paper at the safe deposit box or with notary, but for me an SD card is enough.

Then the open question is how to store sub-keys. You can store them in your home directory, but then you need to enter lengthy passphrase every now and then, plus gpg-agent when used conveniently is not secure - your secrets can be extracted from memory. Here the YubiKey come to save the day. You can use them to store your sub-keys, and in theory these keys can not be extracted from there.

For convenience I always aim to have two YubiKeys set up in the same way. One to have with me, and another to have close to my notebook. In my security model, it is enough.

Unfortunately, a while ago I lost one of my YubiKeys. Despite that, I’ve been using the remaining one since then. A couple of days ago my subkeys expired. Usually every year I extend the expiry date by a year. This time I decided to recreate subkeys. I’ve done it, then I needed to set up two new YubiKeys. While it is not that much-complicated process, after setting up the first one, I found it took me definitely too much time and I forgot about some customizations. I noticed them missing only when I tested the newly set up YubiKey. It’s behavior was not exactly what I expected. If you do such a setup once every couple years, it is hard to remember everything. This is a bit lengthy story why I write this post. I wrote it for myself. If you find it useful, even better.

Setup

Step 0. Install dependencies

On my Fedora 38, I needed only to install additionally a missing package providing ykman:

sudo dnf install yubikey-manager

Other then that, all dependencies where already provided. In case, if you encounter problems of missing packages, look at the instruction HERE.

Step 1. Initial PGP module setup

1.1. (optionally) reset your YubiKey’s PGP module

Optionally, if the YubiKey you have got, is not new, you can reset it:

$ ykman openpgp reset -f
Resetting OpenPGP data, don't remove the YubiKey...
Success! All data has been cleared and default PINs are set.
PIN:         123456
Reset code:  NOT SET
Admin PIN:   12345678

It should reset PIN and Admin PIN to 123456 and 12345678 respectively. We can check status:

$ ykman openpgp info
OpenPGP version:            3.4
Application version:        5.4.3
PIN tries remaining:        3
Reset code tries remaining: 0
Admin PIN tries remaining:  3
Require PIN for signature:  Once
Touch policies:
  Signature key:      Off
  Encryption key:     Off
  Authentication key: Off
  Attestation key:    Off

$ gpg --card-status
Reader ...........: Yubico YubiKey OTP FIDO CCID 00 00
Application ID ...: D2760001240100000006233508650000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: 23350865
Name of cardholder: [not set]
Language prefs ...: [not set]
Salutation .......:
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: off
UIF setting ......: Sign=off Decrypt=off Auth=off
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

YubiKey’s OpenPGP function has been reset.

1.2 Enable kdf-setup

Before you do anything else, it is good to setup kdf. From my experience kdf can not be set after changing PIN or moving keys.2 Once you do one or the other, the PGP module has to be reset to make it possible again to set it.

$ gpg --edit-card

Reader ...........: Yubico YubiKey OTP FIDO CCID 00 00
Application ID ...: D2760001240100000006233508650000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: 23350865
Name of cardholder: [not set]
Language prefs ...: [not set]
Salutation .......:
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: off
UIF setting ......: Sign=off Decrypt=off Auth=off
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

gpg/card> admin
Admin commands are allowed

gpg/card> kdf-setup

Enabling KDF ensures PIN is not stored on the YubiKey, only its hash. It needs to be done before changing PIN. More.

1.3. Change PIN and Admin PIN

gpg/card> passwd
gpg: OpenPGP card no. D2760001240100000006233508650000 detected

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 1
PIN changed.

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 3
PIN changed.

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? Q

More.

Step 2. Transfer keys

In this step, I access the secure storage to get private keys and move them to YubiKey.

If you don’t use LUKS to store your keys, you can skip the point 1.2.

2.1. open cold storage

Depends whether you followed Dr Duh advise to use LUKS for storage of private keys, you might read this this point or skip it (Dr Duh on backup).

In my setup, I made two partitions on the USB. One encrypted with private keys, and the other with public keys and notes and change logs. Once you do such operations once a year, or less, it is handy to remind yourself what you’ve done last year.

First we need to decrypt the secret storage:

sudo cryptsetup luksOpen /dev/xvdi1 secret
# you need to enter password to your encrypted luks

The word ‘secret’ above is a sort of an alias. It represents a mapper name under which the decrypted device will appear in /dev/mapper/, so after executing the command, you would access the decrypted device via /dev/mapper/secret.

Once the encrypted device has been opened (decrypted) we can mount it:

export DIR_SECRET="/mnt/secret"
export DIR_PUBLIC="/mnt/public"

sudo mkdir -p "${DIR_SECRET}"
sudo mkdir -p "${DIR_PUBLIC}"

sudo mount /dev/mapper/secret "${DIR_SECRET}"
sudo mount /dev/xvdi2 "${DIR_PUBLIC}"

In the above snippet I also mount the public part and set environment variables the are used in the other of following snippets.

In the above example I used /dev/xvdi1 and /dev/xvdi2 as devices, but these you need to change. You can find your device names with lsblk.

2.2. install sub-keys on YubiKey

Once I can access my cold storage, time to create temporary GnuPG home, and by that temporary keyring and then import sub-keys. Why temporary keyring? Because the process of moving keys from local keyring to a smarcard (YubiKey) is destructive for local keyring. After the move, the keys no longer reside in the local keyring and this process is not reversible.

If you want to setup more then one YubiKey, it might want to apply steps 2.2.1 - 2.2.3 for every YubiKey you want to setup.

2.2.1. make temporary GnuPG home

Ok, let’s create GnuPG home:

export GNUPGHOME="$(mktemp -d -t "gnupg_$(date +%Y%m%d%H%M)_XXX")"

cp "${DIR_PUBLIC}/extra/gpg.conf" "${GNUPGHOME}"/

This will create a temporary directory like /tmp/gnupg_202310062007_Tyh and assign it to GNUPGHOME. From that point, gpg will always use the given directory withing current shell session.

Then I copy my gpg.conf there for my convenience.

At this point the keyring still doesn’t exist. It is created the first time the gpg is called:

$ gpg -K
gpg: keybox '/tmp/gnupg_202310062007_Tyh/pubring.kbx' created
gpg: /tmp/gnupg_202310062007_Tyh/trustdb.gpg: trustdb created
2.2.2. import sub-keys

Now we are ready to import sub-keys. Since I store only sub-keys on YubiKey, there is no need to import identity/master key. Importing sub-keys is enough:

$ gpg --import "${DIR_SECRET}/private-0x6762037B92E2622E-2023-10-05-subkeys.gpg"
gpg: key 0x6762037B92E2622E: public key "Grzegorz Rynkowski" imported
gpg: To migrate 'secring.gpg', with each smartcard, run: gpg --card-status
gpg: key 0x6762037B92E2622E: secret key imported
gpg: Total number processed: 1
gpg:               imported: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1

$ gpg -K
/tmp/gnupg_202310062007_Tyh/pubring.kbx
---------------------------------------
sec#  rsa4096/0x6762037B92E2622E 2021-10-05 [C] [expires: 2031-10-03]
      Key fingerprint = F347 6719 D066 1632 D61D  0B3B 6762 037B 92E2 622E
uid                   [ unknown] Grzegorz Rynkowski
uid                   [ unknown] [jpeg image of size 4095]
ssb   rsa4096/0xF0952B3BFD6B2FDD 2023-10-05 [E] [expires: 2024-10-04]
ssb   rsa4096/0x27C0F56D7EDF2C87 2023-10-05 [S] [expires: 2024-10-04]
ssb   rsa4096/0x5D618CCCBB13E2B5 2023-10-05 [A] [expires: 2024-10-04]
2.2.3. move sub-keys to YubiKey

Below I show how entire process of moving keys look like. Command key <number> allows you to select or unselect a given key. Command keytocard moves selected key to smart card (here YubiKey). In the process, every time when you move a key, you are asked about keyring passphrase and Admin PIN to the YubiKey. If you haven’t changed you Admin PIN yet, it is 12345678.

$ gpg --edit-key 0x6762037B92E2622E
Secret subkeys are available.

pub  rsa4096/0x6762037B92E2622E
     created: 2021-10-05  expires: 2031-10-03  usage: C
     trust: unknown       validity: unknown
ssb  rsa4096/0xF0952B3BFD6B2FDD
     created: 2023-10-05  expires: 2024-10-04  usage: E
ssb  rsa4096/0x27C0F56D7EDF2C87
     created: 2023-10-05  expires: 2024-10-04  usage: S
ssb  rsa4096/0x5D618CCCBB13E2B5
     created: 2023-10-05  expires: 2024-10-04  usage: A
[ unknown] (1). Grzegorz Rynkowski
[ unknown] (2)  [jpeg image of size 4095]

gpg> key 1

pub  rsa4096/0x6762037B92E2622E
     created: 2021-10-05  expires: 2031-10-03  usage: C
     trust: unknown       validity: unknown
ssb* rsa4096/0xF0952B3BFD6B2FDD
     created: 2023-10-05  expires: 2024-10-04  usage: E
ssb  rsa4096/0x27C0F56D7EDF2C87
     created: 2023-10-05  expires: 2024-10-04  usage: S
ssb  rsa4096/0x5D618CCCBB13E2B5
     created: 2023-10-05  expires: 2024-10-04  usage: A
[ unknown] (1). Grzegorz Rynkowski
[ unknown] (2)  [jpeg image of size 4095]

gpg> keytocard
Please select where to store the key:
   (2) Encryption key
Your selection? 2

pub  rsa4096/0x6762037B92E2622E
     created: 2021-10-05  expires: 2031-10-03  usage: C
     trust: unknown       validity: unknown
ssb* rsa4096/0xF0952B3BFD6B2FDD
     created: 2023-10-05  expires: 2024-10-04  usage: E
ssb  rsa4096/0x27C0F56D7EDF2C87
     created: 2023-10-05  expires: 2024-10-04  usage: S
ssb  rsa4096/0x5D618CCCBB13E2B5
     created: 2023-10-05  expires: 2024-10-04  usage: A
[ unknown] (1). Grzegorz Rynkowski
[ unknown] (2)  [jpeg image of size 4095]

gpg> key 1

pub  rsa4096/0x6762037B92E2622E
     created: 2021-10-05  expires: 2031-10-03  usage: C
     trust: unknown       validity: unknown
ssb  rsa4096/0xF0952B3BFD6B2FDD
     created: 2023-10-05  expires: 2024-10-04  usage: E
ssb  rsa4096/0x27C0F56D7EDF2C87
     created: 2023-10-05  expires: 2024-10-04  usage: S
ssb  rsa4096/0x5D618CCCBB13E2B5
     created: 2023-10-05  expires: 2024-10-04  usage: A
[ unknown] (1). Grzegorz Rynkowski
[ unknown] (2)  [jpeg image of size 4095]

gpg> key 2

pub  rsa4096/0x6762037B92E2622E
     created: 2021-10-05  expires: 2031-10-03  usage: C
     trust: unknown       validity: unknown
ssb  rsa4096/0xF0952B3BFD6B2FDD
     created: 2023-10-05  expires: 2024-10-04  usage: E
ssb* rsa4096/0x27C0F56D7EDF2C87
     created: 2023-10-05  expires: 2024-10-04  usage: S
ssb  rsa4096/0x5D618CCCBB13E2B5
     created: 2023-10-05  expires: 2024-10-04  usage: A
[ unknown] (1). Grzegorz Rynkowski
[ unknown] (2)  [jpeg image of size 4095]

gpg> keytocard
Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 1

pub  rsa4096/0x6762037B92E2622E
     created: 2021-10-05  expires: 2031-10-03  usage: C
     trust: unknown       validity: unknown
ssb  rsa4096/0xF0952B3BFD6B2FDD
     created: 2023-10-05  expires: 2024-10-04  usage: E
ssb* rsa4096/0x27C0F56D7EDF2C87
     created: 2023-10-05  expires: 2024-10-04  usage: S
ssb  rsa4096/0x5D618CCCBB13E2B5
     created: 2023-10-05  expires: 2024-10-04  usage: A
[ unknown] (1). Grzegorz Rynkowski
[ unknown] (2)  [jpeg image of size 4095]

gpg> key 2

pub  rsa4096/0x6762037B92E2622E
     created: 2021-10-05  expires: 2031-10-03  usage: C
     trust: unknown       validity: unknown
ssb  rsa4096/0xF0952B3BFD6B2FDD
     created: 2023-10-05  expires: 2024-10-04  usage: E
ssb  rsa4096/0x27C0F56D7EDF2C87
     created: 2023-10-05  expires: 2024-10-04  usage: S
ssb  rsa4096/0x5D618CCCBB13E2B5
     created: 2023-10-05  expires: 2024-10-04  usage: A
[ unknown] (1). Grzegorz Rynkowski
[ unknown] (2)  [jpeg image of size 4095]

gpg> key 3

pub  rsa4096/0x6762037B92E2622E
     created: 2021-10-05  expires: 2031-10-03  usage: C
     trust: unknown       validity: unknown
ssb  rsa4096/0xF0952B3BFD6B2FDD
     created: 2023-10-05  expires: 2024-10-04  usage: E
ssb  rsa4096/0x27C0F56D7EDF2C87
     created: 2023-10-05  expires: 2024-10-04  usage: S
ssb* rsa4096/0x5D618CCCBB13E2B5
     created: 2023-10-05  expires: 2024-10-04  usage: A
[ unknown] (1). Grzegorz Rynkowski
[ unknown] (2)  [jpeg image of size 4095]

gpg> keytocard
Please select where to store the key:
   (3) Authentication key
Your selection? 3

pub  rsa4096/0x6762037B92E2622E
     created: 2021-10-05  expires: 2031-10-03  usage: C
     trust: unknown       validity: unknown
ssb  rsa4096/0xF0952B3BFD6B2FDD
     created: 2023-10-05  expires: 2024-10-04  usage: E
ssb  rsa4096/0x27C0F56D7EDF2C87
     created: 2023-10-05  expires: 2024-10-04  usage: S
ssb* rsa4096/0x5D618CCCBB13E2B5
     created: 2023-10-05  expires: 2024-10-04  usage: A
[ unknown] (1). Grzegorz Rynkowski
[ unknown] (2)  [jpeg image of size 4095]

gpg> key 3

pub  rsa4096/0x6762037B92E2622E
     created: 2021-10-05  expires: 2031-10-03  usage: C
     trust: unknown       validity: unknown
ssb  rsa4096/0xF0952B3BFD6B2FDD
     created: 2023-10-05  expires: 2024-10-04  usage: E
ssb  rsa4096/0x27C0F56D7EDF2C87
     created: 2023-10-05  expires: 2024-10-04  usage: S
ssb  rsa4096/0x5D618CCCBB13E2B5
     created: 2023-10-05  expires: 2024-10-04  usage: A
[ unknown] (1). Grzegorz Rynkowski
[ unknown] (2)  [jpeg image of size 4095]

gpg> q
Save changes? (y/N) y

When we call gpg --card-status or gpg -K we see the keys are moved:

$ gpg -K
/tmp/gnupg_202310062007_Tyh/pubring.kbx
---------------------------------------
sec#  rsa4096/0x6762037B92E2622E 2021-10-05 [C] [expires: 2031-10-03]
      Key fingerprint = F347 6719 D066 1632 D61D  0B3B 6762 037B 92E2 622E
uid                   [ unknown] Grzegorz Rynkowski
uid                   [ unknown] [jpeg image of size 4095]
ssb>  rsa4096/0xF0952B3BFD6B2FDD 2023-10-05 [E] [expires: 2024-10-04]
ssb>  rsa4096/0x27C0F56D7EDF2C87 2023-10-05 [S] [expires: 2024-10-04]
ssb>  rsa4096/0x5D618CCCBB13E2B5 2023-10-05 [A] [expires: 2024-10-04]

$ gpg --card-status
Reader ...........: Yubico YubiKey OTP FIDO CCID 00 00
Application ID ...: D2760001240100000006233508650000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: 23350865
Name of cardholder: [not set]
Language prefs ...: [not set]
Salutation .......:
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa4096 rsa4096 rsa4096
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: on
UIF setting ......: Sign=off Decrypt=off Auth=off
Signature key ....: 4037 79B3 70C3 0978 91DD  DD68 27C0 F56D 7EDF 2C87
      created ....: 2023-10-05 20:41:34
Encryption key....: 6C05 D5A2 D3E9 4008 A92B  76DD F095 2B3B FD6B 2FDD
      created ....: 2023-10-05 20:41:10
Authentication key: 868A 4EAD 1A3E 238E 05C0  7D80 5D61 8CCC BB13 E2B5
      created ....: 2023-10-05 20:41:54
General key info..: sub  rsa4096/0x27C0F56D7EDF2C87 2023-10-05 Grzegorz Rynkowski
sec#  rsa4096/0x6762037B92E2622E  created: 2021-10-05  expires: 2031-10-03
ssb>  rsa4096/0xF0952B3BFD6B2FDD  created: 2023-10-05  expires: 2024-10-04
                                  card-no: 0006 23350865
ssb>  rsa4096/0x27C0F56D7EDF2C87  created: 2023-10-05  expires: 2024-10-04
                                  card-no: 0006 23350865
ssb>  rsa4096/0x5D618CCCBB13E2B5  created: 2023-10-05  expires: 2024-10-04
                                  card-no: 0006 23350865

Notice ssb> at the beginning of the sub-key line. It indicates that a private key is moved to the smart card.

2.2.4. remove temporary keyring

At this point the keyring doesn’t contain any secrets, still it doesn’t harm to remember about cleanup:

srm -rf "${GNUPGHOME}"

2.3. close cold storage

Once we planted sub-keys in all yubikeys we wanted we can save the logs and close the secure storage.

# umount public part
sudo umount "${DIR_PUBLIC}"

# umount encrypted part
sudo umount "${DIR_SECRET}"
sudo cryptsetup luksClose secret

At this point we can take the USB stick or SD card representing the cold storage and put it at the shelf where is lives :)

Step 3. Post-transfer PGP module setup

This step can be done anywhere.

set touch policy

Touch policy is a strategy whether and if so, how the touch is used. It is not available on all YubiKey devices so you need to first check HERE whether it works with your device. These days, I buy only YubiKey Series 5.

If you are not familiar with YubiKey Series 5 yet, you can set it up in a way, no action will be processed unless you touch your YubiKey when the action happen. You can basically set it up in two ways:

  • option ‘On’ requires a touch on accessing a key,
  • option ‘Cache’ requires a touch on accessing a key, but if touch happened within last 15 seconds, request is processed without necessity to touch the YubiKey again3.

The cache can be set to the keys you want to be cached. In my use cases, I set ‘Cached’ to all three subkeys. Imagine:

  • signing commits when you rebase - multiple requests
  • retriving more then one secret from pass - multiple requests
  • git push (SSH auth) - multiple requests

Your case might be different. In mine, without ‘Cached’ I would need to touch YubiKey, sometimes many, many times.

This is how you can set the cached strategy for touch:

$ ykman openpgp keys set-touch -f -a 12345678 sig cached
$ ykman openpgp keys set-touch -f -a 12345678 dec cached
$ ykman openpgp keys set-touch -f -a 12345678 aut cached

Of course you need to fill your own Admin PIN if you already changed it.

If we check PGP module info we see it is set:

$ ykman openpgp info
OpenPGP version:            3.4
Application version:        5.4.3
PIN tries remaining:        3
Reset code tries remaining: 0
Admin PIN tries remaining:  3
Require PIN for signature:  Once
Touch policies:
  Signature key:      Cached
  Encryption key:     Cached
  Authentication key: Cached
  Attestation key:    Off

$ gpg --card-status
gpg: keybox '/tmp/gnupg_202310062007_Tyh/pubring.kbx' created
Reader ...........: Yubico YubiKey OTP FIDO CCID 00 00
Application ID ...: D2760001240100000006233508650000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: 23350865
Name of cardholder: [not set]
Language prefs ...: [not set]
Salutation .......:
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa4096 rsa4096 rsa4096
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: on
UIF setting ......: Sign=on Decrypt=on Auth=on
Signature key ....: 4037 79B3 70C3 0978 91DD  DD68 27C0 F56D 7EDF 2C87
      created ....: 2023-10-05 20:41:34
Encryption key....: 6C05 D5A2 D3E9 4008 A92B  76DD F095 2B3B FD6B 2FDD
      created ....: 2023-10-05 20:41:10
Authentication key: 868A 4EAD 1A3E 238E 05C0  7D80 5D61 8CCC BB13 E2B5
      created ....: 2023-10-05 20:41:54
General key info..: [none]

In the snippet above you can notice that in the gpg --card-status output the ‘UIF setting’ is enabled now. If you go back in this article to find previous card status I notice it wasn’t set earlier. GPG’s ‘UIF setting’ and YubiKey ’touch policy’ are overlapping. If I’m not mistaken, YubiKey touch policy is implemented using UIF. Therefore, do not try to set UIF manually. It will disable the touch policy we set here.

Similarly, there is no need to enable ‘Signature PIN’. If you set this option to ‘force’, you will be asked about PIN on every signature request. It provides very same security level as the touch policy without caching, at the same time being much less convenient.

(optional) Add more information

$ gpg --card-edit

Reader ...........: Yubico YubiKey OTP FIDO CCID 00 00
Application ID ...: D2760001240100000006233508650000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: 23350865
Name of cardholder: [not set]
Language prefs ...: [not set]
Salutation .......:
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa4096 rsa4096 rsa4096
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: on
UIF setting ......: Sign=on Decrypt=on Auth=on
Signature key ....: 4037 79B3 70C3 0978 91DD  DD68 27C0 F56D 7EDF 2C87
      created ....: 2023-10-05 20:41:34
Encryption key....: 6C05 D5A2 D3E9 4008 A92B  76DD F095 2B3B FD6B 2FDD
      created ....: 2023-10-05 20:41:10
Authentication key: 868A 4EAD 1A3E 238E 05C0  7D80 5D61 8CCC BB13 E2B5
      created ....: 2023-10-05 20:41:54
General key info..: [none]

gpg/card> admin
Admin commands are allowed

gpg/card> name
Cardholder's surname: Rynkowski
Cardholder's given name: Greg

gpg/card> url
URL to retrieve public key: https://rynkowski.pl/pgpkey.txt

gpg/card> login
Login data (account name): greg@rynkowski.pl

gpg/card> lang
Language preferences: en

gpg/card> salutation
Salutation (M = Mr., F = Ms., or space): M

gpg/card> list

Reader ...........: Yubico YubiKey OTP FIDO CCID 00 00
Application ID ...: D2760001240100000006233508650000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: 23350865
Name of cardholder: Greg Rynkowski
Language prefs ...: en
Salutation .......: Mr.
URL of public key : https://rynkowski.pl/pgpkey.txt
Login data .......: greg@rynkowski.pl
Signature PIN ....: not forced
Key attributes ...: rsa4096 rsa4096 rsa4096
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: on
UIF setting ......: Sign=on Decrypt=on Auth=on
Signature key ....: 4037 79B3 70C3 0978 91DD  DD68 27C0 F56D 7EDF 2C87
      created ....: 2023-10-05 20:41:34
Encryption key....: 6C05 D5A2 D3E9 4008 A92B  76DD F095 2B3B FD6B 2FDD
      created ....: 2023-10-05 20:41:10
Authentication key: 868A 4EAD 1A3E 238E 05C0  7D80 5D61 8CCC BB13 E2B5
      created ....: 2023-10-05 20:41:54
General key info..: [none]

gpg/card> quit

(optional) Disable OTP

Very often while using YubiKey with touch policy set, you might encounter touching the yubikey too early. More than often, these get automatically passed to pinentry leading to obviously to auth failure. This is because YubiKey by default supports short and long press. The short press is the OTP feature.

Quote from Dr Duh guide:

YubiKey has two configurations, invoked with either a short or long press. By default, the short-press mode is configured for HID OTP; a brief touch will emit an OTP string starting with cccccccc

You can swap actions after short nad long press or disable OTP. In my case I don’t use OTP, so I disable it:

% ykman config usb -d OTP
USB configuration changes:
Disable Yubico OTP
The YubiKey will reboot
Proceed? [y/N]: y

Final

This is it. A new YubiKey to auth, sign and decrypt is ready.

For more details I refer to brilliant Dr Duh guide HERE.


Update on 2024-03-14: Added section ‘Disable OTP’


  1. In Polish, word ‘duh’ sounds the same as the word ‘duch’ and the latter means a ghost. This meaning might refer to the anonymity and invisibility cryptography can provide. Maybe Dr Duh is a Pole? ↩︎

  2. Same pointed out in the PR here↩︎

  3. In addition, you can choose variants ‘Fixed’ and ‘CachedFixed’ that represent ‘On’ and ‘Cached’ but being fixed until you change the keys. ↩︎