My braindumps

Use your Yubikey Neo for SSH authentication

I've been fighting with gnome-keyring, ssh-agent, gpg and my yubikey to use a GPG authentication subkey for SSH authentication, but never managed to get that working reliably. Both the gpg-ssh-agent and gnome-keyring refused to pick up the authentication subkey, which meant that ssh -l kept reporing The agent has no identities.

So I gave up and tried another path: using the authentication slot of the PIV applet on the Yubikey to store my SSH key. That worked! This seems to be because gnome-keyring (which has often frustrated my attempts to use smart cards, but I have otherwise always found to convenient to ditch) since 3.28 - which is shipped with Ubuntu 18.04 - no longer implements it's own ssh-agent, but just wraps OpenSSH's ssh-agent.

This is what I did (on Ubuntu 18.04):

  1. Install yubikey-piv-manager:

    $ sudo add-apt-repository ppa:yubico/stable
    $ sudo apt update
    $ sudo apt install yubikey-piv-manager
  2. Use the yubikey-piv-manager to set a device PIN and management key.

  3. Use the yubikey-piv-manager to create an Authentication certificate.

  4. Test that ssh itself can use the pubkey from the token (or jump to the next step if you're impatient):

    1. Find the path to your opensc pkcs11 module, on debian/ubuntu you can use:

      $ dpkg -L opensc-pkcs11 | grep \/\$ | head -1
    2. Export the public key in ssh pubkey format:

      $ ssh-keygen -D $(dpkg -L opensc-pkcs11 | grep \/\$ | head -n1 ) -e >
    3. (Optionally edit the exported key to add a name behind the actual key.)

    4. Copy the pub to some ssh host:

      $ cat | ssh my-test-host "cat > ~/.ssh/authorized_keys"
    5. Connect to the host using the key on your token:

      $ ssh -I $(dpkg -L opensc-pkcs11 | grep \/\$ | head -n1 ) my-test-host echo "It works!"
  5. Use ssh-add to load the keys on your yubikey PIV applet in your SSH agent:

    $ ssh-add -e /usr/lib/x86_64-linux-gnu/
  6. Now you should be able to connect to your test host:

    $ ssh my-test-host echo "SUCCESS!"

Because ssh-agent does not automatically reconnect to the token if you remove and reinsert it, I placed the following script in ~/bin/ssh-init-pkcs11:

set -eu

PKCS11_MODULE="$(dpkg -L opensc-pkcs11 | grep \/\$ | head -1)"

if ssh-add -l | grep -q opensc-pkcs11; then
    # Remove any stale loaded keys from token, ssh-agent does not automatically
    # reconnect with the token when you reinsert it.
    ssh-add -e "${PKCS11_MODULE}"

# Tell ssh-agent to use the keys on the token
ssh-add -s "${PKCS11_MODULE}"

Now you can just run ssh-init-pkcs11 after inserting your token to unlock it for use with ssh.