As a reminder, you can check out my overview post if you’re curious about why and in what ways I started using GPG and Yubikey. If you haven’t set up your GPG keys yet, I also talk about a simple flow in my second post.
I’ve got multiple Yubikeys configured across different devices and primarily use them for password management and SSH authentication. Rather than keeping physical subkeys on each of these machines, I instead have a dedicated Yubikey for each device that hosts the subkeys, keeping them protected from direct exposure.
In order to have a simpler setup, I maintain a single encryption, signing, and authentication subkey set that is copied to each of my Yubikeys. By design, when you move a subkey over to a Yubikey, the local instance is destroyed. To maintain the same subkey, you have to copy your GPG folder prior to transferring the keys in order to maintain the subkeys.
Alternatively, you can opt to not save your changes during the interactive CLI, but it’s very subtle and I tend to forget every time.
When a Yubikey is plugged in without any keys configured, running
gpg --card-status should reflect something like this:
Reader ...........: Yubico YubiKey CCID Application ID ...: D2760001240103040006144075690000 Application type .: OpenPGP Version ..........: 3.4 Manufacturer .....: Yubico Serial number ....: 14407569 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 Signature key ....: [none] Encryption key....: [none] Authentication key: [none] General key info..: [none]
Notice how the signature, encryption, and authentication keys are all marked as
Moving subkeys to yubikey
The act of transferring a subkey over to a Yubikey is destructive, and will result in a stub remaining on the local machine that does nothing without access to the Yubikey itself. Below are the steps I take to transfer each subkey one at a time:
- We need to edit the local key via
gpg --expert --edit-key firstname.lastname@example.org
- Make sure to select the proper key using
key 1or whatever number corresponds to the subkey. When this is done, a
*will appear next to the key
keytocard, which will prompt for the master secret key password (this is for the master key, not the yubikey) and then the yubikey admin password, which is
- Do the same for each other subkey by deselecting the current subkey (e.g.
key 1again) and then selecting the next subkey (e.g.
yto the prompt to save the changes and produce local stubs
Adding details such as public key URL and name to Yubikey
Out of the box, your Yubikey comes with no information and a default admin password and regular password.
- The admin password is used to change your regular password and transfer GPG keys over to the Yubikey.
- The regular password is used for authentication whenever your computer needs to leverage a key stored on your Yubikey.
Whenever I’m setting up a new Yubikey, here are the steps I take:
- We need to edit the card via
gpg --expert --edit-card
- Access the admin commands via
passwdto change the passwords
- To change the regular password, use
123456as the default and then provide the new password
- To change the admin password, use
12345678as the default and then provide the new password
- To change the regular password, use
urlto change the url. I use
https://chipsenkbeil.com/keys/chipsenkbeil.pub.gpgas the public key url.
- Providing this enables us to pull in the public keys for a new Yubikey
- Setting this requires re-entering the admin Yubikey password.
- Providing this enables us to pull in the public keys for a new Yubikey automatically via
nameto change the surname (Senkbeil) and given name (Chip).
langto change the language to English (en).
quitto exit and save changes
Removing master key from local system
With the subkeys moved over to our Yubikey, it’s a good idea to remove the master key from our local system. You should have a backup of this either in a paper form or in a secure storage you trust! I only use my master key to manage subkeys, delegating all other operations to the subkeys themselves.
To remove the master key, we want to delete the local secret key using
gpg --delete-secret-key <ID> where I used
email@example.com as it matches one of
my identity’s email addresses.
When this is done,
gpg -K will be blank. This means that we need to re-import
our key information. To do this, edit our card using
gpg --expert --edit-card.
From there, since we have the public key available and defined in the url,
we can run
fetch to get and import the information.
gpg -K should reflect the private master key with a
# to indicate not
locally available and
> for subkeys to imply the same.
By default, the Yubikey will be sensitive to touch as it attempts to provide a one-time password (OTP). Since I don’t use that functionality myself, I’d prefer to disable it so I don’t accidentally activate it when brushing the key with my leg when using a laptop. To do this, I need to install the yubikey manager to configure it:
arch -arm64 brew install ykman
From there, I’m able to see a connected Yubikey via
ykman info and the modes
it has (OTP/FIDO/CCID). For OpenPGP applications, we need CCID
a. Setting the modes is done using a string in the form of
ykman mode OTP+FIDO+CCID and providing just
ykman mode CCID will configure
the Yubikey to only be configured for CCID applications.
ykman info should now reflect the following:
Device type: YubiKey 5C Nano Serial number: 14407569 Firmware version: 5.2.7 Form factor: Nano (USB-C) Enabled USB interfaces: CCID Applications OTP Disabled FIDO U2F Disabled OpenPGP Enabled PIV Enabled OATH Enabled FIDO2 Disabled