Using SSH User Certificates with PIV keys

This is a step-by-step on how to setup SSH user certificates using PIV for hardware-backed keys. This guide is primarily for a macOS or Linux system.

Prerequisites

  • a YubiKey with the PIV application loaded

  • the yubico-piv-tool software

  • the ykcs11 PKCS#11 module

  • OpenSSH

Note
This has been tested as working with OpenSSH version 7.2p2. It has also been tested as not working with OpenSSH version 6.9p1.

Steps

  1. Generate an "ssh user CA" key and trust it for this account on this host.

    ssh-keygen -N '' -C user-ca -f ~/.ssh/ca
    sed 's/^/cert-authority /' ~/.ssh/ca.pub > ~/.ssh/authorized_keys
    
  2. Generate or import a key in PIV slot 9c that requires touch.

    1. Import key and certificate:

      yubico-piv-tool -s 9c -a import-key -i key.pem --pin-policy=never --touch-policy=always
      yubico-piv-tool -s 9c -a import-certificate -i cert.pem
      
    2. Generate a key and sign a certificate. (Note the second operation will require touch)

      yubico-piv-tool -a generate -s 9c -A RSA2048 --pin-policy=never --touch-policy=always -o public.pem
      yubico-piv-tool -a selfsign-certificate -s 9c -S "/CN=SSH key/" -i public.pem -o cert.pem
      yubico-piv-tool -a import-certificate -s 9c -i cert.pem
      
  3. Double check that the key appears in slot 9c (optional)

    yubico-piv-tool -a status
    
  4. Clear the SSH agent

    ssh-add -D
    ssh-add -e /PATH/TO/libykcs11.so
    
    • Make sure to use the correct path (e.g. /usr/local/lib) and extension (.so for Linux, .dylib for macOS) for libykcs11.

    • Beware that ssh-add -D doesn’t seem to clear PKCS#11 libraries, only keys (link).

  5. Add PIV to the SSH agent (will prompt for PIV PIN)

    ssh-add -s /PATH/TO/libykcs11.so
    
  6. Get the public key from PIV and sign it using the CA key. This produces ~/.ssh/id_rsa-cert.pub

    ssh-add -L > ~/.ssh/id_rsa.pub
    ssh-keygen -s ~/.ssh/ca -I identity -n "${LOGNAME}" ~/.ssh/id_rsa.pub
    
  7. Authenticate to the target system using the new key:

    ssh user@remote.example.com
    

If you have followed these steps to the letter, you will not be asked for the PIV PIN, but your YubiKey will start blinking, waiting for touch.

More info

For more information see the CERTIFICATES section of ssh-keygen(1).

Notes

  • The ca key is stored in a file in this example, but could also be stored on another YubiKey in a similar fashion.

  • The target system must have the ca key configured as a cert-authority, either via a user’s authorized_keys file, or using sshd_config.

Thanks

Thanks to Christopher Harrell and Dean Sutherland formerly of the Paranoids, Information Security at Yahoo, Inc. for providing the instruction and the testing.