---
title: YubiKey setup
---

[[_TOC_]]

# How to

## Use the PIV feature as a two-factor ssh-rsa key

### Token setup

YubiKey 5-series tokens, which support the [FIPS 201](https://en.wikipedia.org/wiki/FIPS_201)
standard also known as PIV, can be used as a convenient second factor to for ssh
public key authentication.

While the YubiKey supports either RSA or ECC certificates for this, we'll use
RSA since it's the most compatible across all SSH servers. For example, some BMC
only support `ssh-rsa` keys. This has also been observed on Pantheon.io, a DevOps
platform for websites. For modern SSH servers, the `ed25519-sk` key type is
preferred.

First, one must install [yubikey-manager](https://github.com/Yubico/yubikey-manager).
On Debian 11 (bullseye), a simple `apt install yubikey-manager` is sufficient. On
older versions of Debian, one should install it via `pip3` in order to have a
sufficiently recent version of the tool.

 1. Reset all PIV config/data on the token: `ykman piv reset`
 2. Define new PIN (the default is `123456`): `ykman piv change-pin`
   * *The PIN must be between 6 and 8 characters long, and supports any type of
   alphanumeric characters. For cross-platform compatibility, numeric digits are
   recommended.*
 3. Define new PUK (Personal Unblocking Key, used when PIN retries have been
 exceeded): `ykman piv change-puk`
 2. Define a management key: `piv change-management-key -pt`
 3. Generate RSA key: `ykman piv keys generate --algorithm RSA2048 --pin-policy
 ONCE --touch-policy CACHED 9a pubkey.pem`
 4. Generate certificate: `ykman piv certificates generate --valid-days 3650
 --subject "CN=ssh" 9a pubkey.pem`
 5. Verify with `ykman piv info`

This will create a 2048-bits RSA certificate in slot 9a of the PIV token device.
The PIN will be required only once per-session (`--pin-policy ONCE`) but touch
will be required at every use and remembered for 15 seconds afterwards
(`--touch-policy CACHED`).

The next step is to install and start [yubikey-agent](https://github.com/FiloSottile/yubikey-agent)
which is a small daemon written in Go that act as an ssh-agent for the YubiKey.
Installation instructions which work with Debian can be found here:

https://github.com/FiloSottile/yubikey-agent/blob/main/systemd.md

The `yubikey-agent -setup` step can be skipped, as we've already set up the
token with the above. `yubikey-agent`'s own setup routine makes different,
hard-coded choices with regard to the PIN and PUK (identical), certificate type
(ECC) and other small things.

Once the agent is setup and running in the background, the SSH public key can be
retrieved from the token using the following command: `ssh-add -L`.

At this point it may be useful to install the `libnotify-bin` package on Debian
which allows the agent to send a desktop notification when the token needs to be
touched to perform an authentication operation. This is especially useful when
the token LED, which flashes when touch is requested, isn't well into view.

These instructions are spinned off from those found at: https://eta.st/2021/03/06/yubikey-5-piv.html

### Configure SSH

If not done already, now is a good time to setup the ssh configuration for the
TPO jump host, see [ssh-jump-host](/doc/ssh-jump-host/) for these instructions.

To have the `ssh` command use `yubikey-agent` when connecting to TPO hosts, add
this line in `~/.ssh/config` under `Host *.torproject.org`:

    IdentityAgent /run/user/1000/yubikey-agent/yubikey-agent.sock

If you also want to use `ed25519_sk`-type keys based on the modern FIDO2
protocol for non-TPO hosts, you may add this at the end of `~./ssh/config`:

    Host *
      IdentityAgent /dev/null
      IdentityFile ~/.ssh/id_ed25519_sk
