YubiKey-5 Guide

Don’t let your PGP or SSH keys be copied from your computer. Protect your keys in an OpenPGP Card.

You may want to review the typographical conventions used on this site.

Introduction

ykman info
Device type: YubiKey 5 NFC
Serial number: xxxxxxxx
Firmware version: 5.7.1
...

Make note of the YubiKey’s serial number. This guide includes the device’s family and serial number, in a string like yubikey-xxxxxxxx, as part of credential identifiers.

FIDO/FIDO2/Passkey

You can display basic FIDO configuration information with the command:

ykman fido info

The stored FIDO2/Passkey credentials can be listed with the command:

ykman fido credentials list

Reset FIDO

You can delete all FIDO credentials and restore factory settings with the command:

ykman fido reset

Configure FIDO

ykman fido access set-min-length 6
ykman fido access change-pin
ssh-keygen -t ed25519-sk \
    -O resident \
    -O verify-required \
    -O application=ssh:john.doe+yubikey-xxxxxxxx@example.com

OpenPGP

You can display basic OpenPGP configuration information with the command:

ykman openpgp info

More detailed OpenPGP configuration information can be displayed using GnuPG:

gpg --card-status

Reset OpenPGP

You can delete all OpenPGP keys and data and restore factory settings with the command:

ykman openpgp reset

The output from the reset shows that the default reset code is not set, the default admin PIN is 12345678, and the default user PIN is 123456.

Configure OpenPGP

gpg --card-edit
gpg/card> admin
Admin commands are allowed

Enable Key Derived Function (KDF) support. KDF can only be enabled right after reset, before changing any PINs or generating any keys. Use list to verify the KDF setting before proceeding.

gpg/card> kdf-setup

gpg/card> list
...
KDF setting ......: off
...

Change the user PIN, admin PIN, and reset code.

gpg/card> passwd

Every signature generation should require entering the user PIN. The forcesig command toggles the current setting, so verify the setting is correct with list after toggling.

gpg/card> forcesig

gpg/card> list
...
Signature PIN ....: forced
...

Set the YubiKey owner’s surname/last and given/first names.

gpg/card> name
Cardholder's surname: Doe
Cardholder's given name: John

Set the YubiKey owner’s preferred language as an ISO 639 two-letter language code.

gpg/card> lang
Language preferences: en

By default, the YubiKey OpenPGP application generates keys using RSA 2048. We want to change key generation to use either RSA 4096 or Curve 25519. The following example configures Curve 25519.

gpg/card> key-attr

Changing card key attribute for: Signature key
Please select what kind of key you want:
   (1) RSA
   (2) ECC
Your selection? 2
Please select which elliptic curve you want:
   (1) Curve 25519 *default*
   (4) NIST P-384
   (6) Brainpool P-256
Your selection? 1
The card will now be re-configured to generate a key of type: ed25519

Changing card key attribute for: Encryption key
Please select what kind of key you want:
   (1) RSA
   (2) ECC
Your selection? 2
Please select which elliptic curve you want:
   (1) Curve 25519 *default*
   (4) NIST P-384
   (6) Brainpool P-256
Your selection? 1
The card will now be re-configured to generate a key of type: cv25519

Changing card key attribute for: Authentication key
Please select what kind of key you want:
   (1) RSA
   (2) ECC
Your selection? 2
Please select which elliptic curve you want:
   (1) Curve 25519 *default*
   (4) NIST P-384
   (6) Brainpool P-256
Your selection? 1
The card will now be re-configured to generate a key of type: ed25519

Generate OpenPGP keys on the YubiKey using the configured key attributes. The following example declines making an off-card backup (so that key material never leaves the YubiKey), sets the key lifetime to never expire, and configures the USER-ID for the keys to include the YubiKey serial number.

gpg/card> generate

Make off-card backup of encryption key? (Y/n) n

Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: John Doe
Email address: john.doe+yubikey-xxxxxxxx@example.com
Comment:
You selected this USER-ID:
    "John Doe <john.doe+yubikey-xxxxxxxx@example.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O

Require touch confirmation for the OpenPGP keys.

gpg/card> uif 1 on

gpg/card> uif 2 on

gpg/card> uif 3 on

Quit the GnuPG card-edit session.

gpg/card> quit

Set the number of allowed PIN retries to something slightly more forgiving than the default three.

ykman openpgp access set-retries 8 8 8

Verify the OpenPGP settings with the following commands:

ykman openpgp info
gpg --card-status

Upload Your Public Key to the Keyservers

To make your OpenPGP public key easy to find, you can upload your public key to the keyservers.

gpg --send-keys XXXXXXXXXXXXXXXX

If you are using the keys.openpgp.org keyserver, you need to verify each email address by which your public key should be searchable. Execute the following command, copy the returned URL into your web browser, and follow the instructions at that URL.

gpg --export XXXXXXXXXXXXXXXX | curl -T - https://keys.openpgp.org/

Information about the design and privacy of keys.openpgp.org is available at the following links.

OpenSSH Support

FIDO2 in OpenSSH

OpenSSH version 8.3 added native support for FIDO2 authenticator keys.

GnuPG in OpenSSH

Ensure that your ~/.gnupg/gpg-agent.conf enables ssh-agent support.

# Enable OpenSSH Agent (ssh-agent) protocol support.
enable-ssh-support

Ensure that your ~/.profile tells ssh to use gpg-agent instead of ssh-agent.

if [ -z "$SSH_AUTH_SOCK" ]; then
    export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
fi

Kill any running ssh-agent and gpg-agent processes for your user so that the new gpg-agent settings can take effect.

killall -u ${USER} ssh-agent gpg-agent

Log out and log in to set the session environment variables required for ssh to use gpg-agent instead of ssh-agent. Then check that gpg can still see your YubiKey, which has the side-effect of ensuring that gpg-agent is running.

gpg --card-status

At this point, ssh should be able to use the authentication key slot on the YubiKey as an SSH authentication key.

The following command retrieves the SSH-formatted public key from the YubiKey. Place the retrieved public key into ~/.ssh/authorized_keys on the appropriate systems and register the public key with SSH-based services like GitHub or GitLab.

ssh-add -L

If multiple public keys are listed, the authentication Key on the YubiKey is the one that ends with a card number comment that contains the serial number of that YubiKey.

ssh-rsa ... cardno:XXXXXXXXXXXX

Harden OpenSSH

Now that you have a YubiKey that can be used for SSH public key authentication, you should harden your OpenSSH configuration to disable SSH password authentication.

Using the YubiKey on a New Computer

To temporarily configure a new system with the FIDO2 OpenSSH key:

ssh-add -K

To permanently configure a new system with the FIDO2 OpenSSH key:

cd ~/.ssh
ssh-keygen -K

To permanently configure a new system with the OpenPGP key, fetch your public key from the keyservers, then plug in the YubiKey and check the card status to connect that YubiKey to the matching public key.

gpg --recv-keys XXXXXXXXXXXXXXXX
gpg --card-status