OpenSSH key management with YubiKey PIV and FIDO2
As my SSH keys for both work and private infrastructure are quite valuable to me I like to have those as secure as fairly possible. The YubiKey provides two features that help in managing my OpenSSH private and public keys.
With the PIV feature the key can generate and store OpenSSH private keys. The FIDO2 feature however stores public keys - think of them as identities. Without FIDO2 the public key is generated on each device and hence you don’t have a portable key-pair. The OpenSSH 8.6+ agent is capable of loading identities from a smart card out-of-the-box, otherwise the individually generated public keys are used by the agent to load the private key from the smart card.
Configure a backup key - This does not get old
As these hardware tokens are unique by design it is pretty easy to lock yourself out of everything should you loose the key in any way. I can’t stress on this fact enough. Therefore I always have a second key ready for registration to services or generating private keys which is always kept somewhere safe.
You’ll need two packages from the official Fedora repositories:
sudo dnf install -y pam_yubico yubikey-manager
Setup PIV and FIDO2
Change the PIN, PUK and Management Key of the PIV module of your key. Default PIN is
123456 and PUK is
$ ykman piv access change-pin Enter the current PIN: 123456 Enter the new PIN: ******** Repeat for confirmation: ******** New PIN set. $ ykman piv access change-puk Enter the current PUK: 12345678 Enter the new PUK: ******** Repeat for confirmation: ******** New PUK set. $ ykman piv access change-management-key --generate --protect Enter the current management key [blank to use default key]: Enter PIN: ********
Set a PIN to the FIDO2 module.
$ ykman fido access change-pin Enter the current PIN: 123456 Enter the new PIN: ******** Repeat for confirmation: ******** New PIN set.
Generate a private key
Generate a private key (e.g. ED25519) with touch and pin requirement in the 9a slot:
$ ykman piv keys generate --algorithm ED25519 --pin-policy ONCE --touch-policy ALWAYS 9a public.pem Enter PIN: ********
The slot 9a is for “PIV Authentication”.
Create a self-signed certificate for that key. The only use for the X.509 certificate is to satisfy PIV/PKCS #11 lib. It is needed to extract the public key from the smart card.
$ ykman piv certificates generate --subject "CN=OpenSSH" --hash-algorithm SHA384 9a pubkey.pem Enter PIN: ******** Touch your YubiKey…
Generate a resident public key
ssh-keygen to generate a public key you can later use in
authorized_keys files on remote systems. The following generates such a key directly on the YubiKey in a FIDO2 slot, making it portable.
ssh-keygen -t ed25519-sk -O resident -O application=ssh:fedora -O verify-required
The resident option instructs
ssh-keygen to store the key handle on the YubiKey, making it easier to use the key across multiple systems as
ssh-add can load the and use the SSH keys from the YubiKey directly. The application option assigns a designated name for the this specific private-public-key-pair and is useful if working with different SSH identities. The verify-required option is mandatory for resident keys and adds requirement to enter a pin on key usage.
If the key is generated with a touch requirement only omit the verify-required option. If you don’t want to use FIDO2 slots omit the resident and application options and make sure to backup generated public keys.
Caching OpenSSH connections
In OpenSSH default configuration you’ll be prompted to touch your key every time you connect to a machine. To let your OpenSSH client cache connections even after you close the terminal session and thus don’t need to touch the key again add the following option to your
Host * ControlMaster auto ControlPath ~/.ssh/S.%r@%h:%p ControlPersist 5m
This will persist a session for 5 more minutes after you stop using it.
Get information on the PIV slot 9a:
$ ykman piv info PIV version: 5.4.3 PIN tries remaining: 3/3 Management key algorithm: TDES CHUID: REDACTED CCC: No data available. Slot 9a: Algorithm: RSA2048 Subject DN: CN=SSH key Issuer DN: CN=SSH key Serial: REDACTED Fingerprint: REDACTED Not before: 2022-01-01 20:00:00 Not after: 2023-01-01 20:00:00
List stored FIDO2 public keys with:
$ ykman fido credentials list ssh:fedora 0000000000000000000000000000000000000000000000000000000000000000 openssh
Any thoughts of your own?
Feel free to raise a discussion with me on Mastodon or drop me an email.