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
Test that your computer can interact with the YubiKey.
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 serial number,
in a string like yubikey-xxxxxxxx
,
as part of credential identifiers to simplify using multiple YubiKeys.
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
Increase the minimum PIN length from four to six.
ykman fido access set-min-length 6
Change the FIDO PIN from the default 123456
.
ykman fido access change-pin
Always require user verification.
ykman fido config toggle-always-uv
Generate a resident FIDO authenticator key for use with SSH. Resident keys store key handle information on the authenticator that simplify using the authenticator on multiple computers.
The default OpenSSH application string is only ssh:
,
and must always begin with ssh:
.
This tutorial sets the application string to include
the YubiKey owner’s name and the YubiKey’s serial number.
ssh-keygen -t ed25519-sk \
-O resident \
-O verify-required \
-O application=ssh:john.doe+yubikey-xxxxxxxx@example.com
The FIDO configuration information should now look something like this:
ykman fido info
AAGUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
PIN: 8 attempt(s) remaining
Minimum PIN length: 6
Always Require UV: On
Credential storage remaining: 99
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
Start a GnuPG session to configure the OpenPGP application; enable required admin commands.
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 ......: on
...
Change the user PIN, admin PIN, and reset code.
gpg/card> passwd
Every PGP 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 RSA 2048 keys.
We want to change key generation to use either RSA 4096 or Curve 25519.
The following example configures Curve 25519.
Use list
to verify the settings.
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
gpg/card> list
...
Key attributes ...: ed25519 cv25519 ed25519
...
Generate OpenPGP keys on the YubiKey using the configured key attributes.
The following example
declines making an off-card backup (so private 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’s 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 all OpenPGP keys (1 = Sign, 2 = Decrypt, 3 = Auth).
Use list
to verify the settings.
gpg/card> uif 1 on
gpg/card> uif 2 on
gpg/card> uif 3 on
gpg/card> list
...
UIF setting ......: Sign=on Decrypt=on Auth=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. Eight attempts is reasonable and matches the FIDO application for consistency.
ykman openpgp access set-retries 8 8 8
Verify the OpenPGP settings with the following commands:
ykman openpgp info
OpenPGP version: 3.4
Application version: 5.7.1
PIN tries remaining: 8
Reset code tries remaining: 8
Admin PIN tries remaining: 8
Require PIN for signature: Always
KDF enabled: True
Signature key:
Fingerprint: xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
Touch policy: On
Decryption key:
Fingerprint: xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
Touch policy: On
Authentication key:
Fingerprint: xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
Touch policy: On
gpg --card-status
Reader ...........: Yubico YubiKey FIDO CCID 00 00
Application ID ...: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: xxxxxxxx
Name of cardholder: John Doe
Language prefs ...: en
Salutation .......:
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: ed25519 cv25519 ed25519
Max. PIN lengths .: 127 127 127
PIN retry counter : 8 8 8
Signature counter : 4
KDF setting ......: on
UIF setting ......: Sign=on Decrypt=on Auth=on
Signature key ....: xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
created ....: YYYY-MM-DD hh:mm:ss
Encryption key....: xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
created ....: YYYY-MM-DD hh:mm:ss
Authentication key: xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
created ....: YYYY-MM-DD hh:mm:ss
General key info..: pub ed25519/xxxxxxxxxxxxxxxx YYYY-MM-DD John Doe <john.doe+yubikey-xxxxxxxx@example.com>
sec> ed25519/xxxxxxxxxxxxxxxx created: YYYY-MM-DD expires: never
card-no: xxxx xxxxxxxx
ssb> ed25519/xxxxxxxxxxxxxxxx created: YYYY-MM-DD expires: never
card-no: xxxx xxxxxxxx
ssb> cv25519/xxxxxxxxxxxxxxxx created: YYYY-MM-DD expires: never
card-no: xxxx xxxxxxxx
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.
Ensure that your ~/.profile
tells ssh
to use gpg-agent
instead of ssh-agent
.
if [; then
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 the OpenSSH authorized_keys
file
on the appropriate systems and register the public key
with SSH-based services like GitHub or GitLab.
ssh-add -L
ssh-ed25519 ... cardno:XXXXXXXXXX
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.
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
FIDO2
To configure a new system with the FIDO2 OpenSSH key:
cd ~/.ssh
ssh-keygen -K
Enter PIN for authenticator:
You may need to touch your authenticator to authorize key download.
Enter passphrase for "id_ed25519_sk_rk_john.doe+yubikey-xxxxxxxx@example.com" (empty for no passphrase):
Enter same passphrase again:
Saved ED25519-SK key ssh:john.doe+yubikey-xxxxxxxx@example.com to id_ed25519_sk_rk_john.doe+yubikey-xxxxxxxx@example.com
Since the private key never leaves the YubiKey, must be unlocked with a PIN, and every use requires touch authorization, using an empty password on the OpenSSH key handle is acceptable.
The above command downloads the resident key handle from the YubiKey and creates two files:
id_ed25519_sk_rk_john.doe+yubikey-xxxxxxxx@example.com
: The OpenSSH private key handleid_ed25519_sk_rk_john.doe+yubikey-xxxxxxxx@example.com.pub
: The OpenSSH public key
You can specify which YubiKey to use by specifying the key handle with ssh -i
,
or you can create symbolic links from the default key handle files to the desired YubiKey files.
cd ~/.ssh
ln -s id_ed25519_sk_rk_john.doe+yubikey-xxxxxxxx@example.com id_ed25519_sk
ln -s id_ed25519_sk_rk_john.doe+yubikey-xxxxxxxx@example.com.pub id_ed25519_sk.pub
OpenPGP
To configure a new system with the OpenPGP key, fetch your public key from the keyservers, 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