Using PIV for SSH through PKCS #11

This is a step-by-step guide on setting up a YubiKey with PIV to work for public-key authentication with OpenSSH through PKCS #11. These instructions apply primarily to macOS and Linux systems.


  • a YubiKey with the PIV application loaded

  • the yubico-piv-tool software (download from link:../yubico-piv-tool/Releases/)

  • OpenSSH

  • For macOS, iOS 10.13 and later are supported

OpenSC is no longer required, since we now have a functional PKCS #11 module, namely ykcs11.

RSA 4096-bit keys are not currently supported due to a limitation in the PIV spec:
We strongly recommend changing the management key; keeping the default management key is explicitly discouraged. The examples given in the following steps assume that you have not yet changed the management key. If you have changed the management key, add --key to the yubico-piv-tool -a import-certificate command below.


Step 1: Import or generate a key in slot 9a (any slot should suffice):

Either import the key (PEM format):

yubico-piv-tool -s 9a -a import-key -i key.pem
If an external key has been imported and a certificate already exists, skip step 2.

or generate the key:

yubico-piv-tool -s 9a -a generate -o public.pem

Step 2: Create a self-signed certificate for that key. The only use for the X.509 certificate is to satisfy PIV/PKCS #11 lib. It needs to be able to extract the public-key from the smartcard, and to do that through the X.509 certificate.

yubico-piv-tool -a verify-pin -a selfsign-certificate -s 9a -S "/CN=SSH key/" -i public.pem -o cert.pem

Step 3: Load the certificate:

yubico-piv-tool -a import-certificate -s 9a -i cert.pem

Step 4: Find out where ykcs11 has been installed. For a Debian-based system, the ykcs11 module ends up in /usr/local/lib/libykcs11. On MacOS, it is in /usr/local/lib/libykcs11.dylib.

Step 5: Export the public key in correct format for SSH and then add it to authorized_keys on the target system.

ssh-keygen -D XXX/ -e
This command will export all keys stored on the YubiKey. The slot order should remain the same, thereby facilitating identification of the public key associated with your targeted private key.

Step 6: Authenticate to the target system using the new key:

ssh -I XXX/

Step 7: (Optional) This can also be set up to work with ssh-agent:

ssh-add -s XXX/

Confirm that the ssh-agent finds the correct key and gets the public key in the correct format by running:

ssh-add -L