yubikey-linux-intro-part2.webp

Part 2 - Using YubiKey with SSH to authenticate to remote SSH servers. Not gonna explain what SSH is and use cases or configuration, but might do a deep-dive if someone is interested.

Note: All configuration is done in Fedora with GNOME DE (applicable 1-to-1 on related distros) and YubiKey 5C / USB (not the Biometric version).



SSH Authentication with YubiKey FIDO2

What is FIDO2?

FIDO2 is an open authentication standard that lets you use hardware security keys (like YubiKey) for passwordless authentication.


OpenSSH + FIDO2

OpenSSH added support for FIDO2 on version 8.2, meaning we can now use the YubiKey alongside (or instead of) traditional password or key-based authentication.

When you authenticate, the cryptographic operations happen directly on the hardware token itself. So even if someone compromises your computer and steals your SSH key files, they still can’t authenticate without physically having your YubiKey.

This offers another layer of security. Every single authentication requires you to physically touch your YubiKey (you can also configure it to require PIN verification if you want more security).


FIDO2 SSH Key Types

There are 2 types of FIDO2 SSH keys:

Non-Resident Keys:

  • The private key is stored as a file on the computer alongside your other SSH keys.
  • This is just like a traditional SSH key, however, the key is useless by itself. It requires your YubiKey to perform any operation (like signing in).
  • These keys don’t consume any of your YubiKey’s credential slots (you can create as many as you want).
  • To authenticate on a SSH server, the private key must be present in your computer and the public key must be present in the target SSH server’s authorized_keys file.

Resident Keys:

  • The private key is stored directly in the YubiKey’s internal memory. No key files are stored on the computer.
  • These keys consume one of your YubiKey’s credential slots (YubiKey 5 holds up to 100). So, if you create resident keys for connecting to dozens of servers, you can run out of slots.
  • To authenticate on a SSH server, you can just plug your YubiKey into any computer (even new) and the SSH agent can “discover” the key on the device and use it to authenticate to the target SSH server with the corresponding public key in its authorized_keys file.


Configuration

Requirements

  • OpenSSH 8.2 or newer for FIDO2 support.
  • The yubikey-manager package, which provides the ykman CLI tool to manage the YubiKey FIDO2 application and more.
# Install SSH
sudo dnf install openssh-clients

# Check OpenSSH version
ssh -V

# Install the "yubikey-manager" package if not already installed
sudo dnf install yubikey-manager

Set YubiKey FIDO2 PIN

Before generating keys or using PIN verification, you must set a FIDO2 PIN on your YubiKey.

# Change or set your FIDO2 PIN
ykman fido access change-pin

# Verify your PIN works
ykman fido access verify-pin

Important: This PIN is separate from PIV PINs and OpenPGP PINs. Each YubiKey application has its own PIN.


Generate SSH Keys

Non-resident keys don’t consume credential slots on the YubiKey, and if the YubiKey is lost or stolen, an attacker cannot obtain the SSH private key from the YubiKey alone.

Key Generation Options:

  • -t <type>: Type of key algorithm to use.
    • ed25519-sk: Use the Ed25519 algorithm (recommended).
    • ecdsa-sk: Alternative if Ed25519 is not supported, usually for old servers.
  • -O verify-required: Requires both PIN and YubiKey touch for every use, else only touch is needed.
  • -C "comment": Add a comment to identify the key. This can be any string but the recommendation is to specify something to identify who create the key and where it was generated.
# Generate non-resident key with PIN verification
ssh-keygen -t ed25519-sk -O verify-required -C "user@hostname"

# You'll be prompted to:
# 1. Touch your YubiKey metal plate
# 3. Choose a passphrase for the key file (optional but recommended)

Resident Key (Portable)

Resident keys are stored on the YubiKey itself, enabling portability across machines. They require a PIN to generate and use.

Key Generation Options:

  • -t <type>: Type of key algorithm to use.
    • ed25519-sk: Use the Ed25519 algorithm (recommended).
    • ecdsa-sk: Alternative if Ed25519 is not supported, usually for old servers.
  • -O <option>
    • -O resident: Creates a resident key stored on the YubiKey.
    • -O application=ssh:hostname: Optional label for multiple SSH credentials. Mainly used to differentiate between all keys stored in the YubiKey.
    • -O verify-required: Requires both PIN and YubiKey touch for every use, else only touch is needed.
  • -C "comment": Add a comment to identify the key. This can be any string but the recommendation is to specify something to identify who created the key and where it was generated.
# Generate resident key with PIN verification
ssh-keygen -t ed25519-sk -O resident -O verify-required -O application=ssh:hostname -C "user@hostname"

# You'll be prompted to:
# 1. Enter your FIDO2 PIN (if verify-required is used)
# 2. Touch your YubiKey metal plate
# 3. Choose a passphrase for the key file (optional but recommended)

Add Public Key to SSH Servers

This step is identical for BOTH key types.

After you generate a key (any type), you get a .pub public key file (e.g., id_ed25519_sk.pub), which needs be added to the target SSH server’s ~/.ssh/authorized_keys file you want to connect.

# Copy generated public key to remote server
ssh-copy-id -i ~/.ssh/id_ed25519_sk.pub user@remote-server

# Or manually append to authorized_keys
cat ~/.ssh/id_ed25519_sk.pub | ssh user@remote-server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

Add Keys to SSH Agent

Once the public key is added to the target SSH server you want to connect, follow these steps:

  • Non-Resident Keys: You need the private key file on your computer to authenticate. Adding the key to the SSH agent is optional.
  • Resident Keys (Agent Required): You need to configure the SSH Agent to fetch the key directly from the YubiKey memory to authenticate. Adding the key to the agent is a requirement for resident keys. This can be done on any new machine you want to connect from. You only need the public key to be in the target SSH server.
# Start ssh-agent (if not already running)
eval "$(ssh-agent -s)"

# Non-Resident: Add private key file to SSH agent
ssh-add ~/.ssh/id_ed25519_sk

# Resident (on any new machine): Discover and load the key from the YubiKey
ssh-add -k

# List loaded keys
ssh-add -l

Using SSH with YubiKey

Once your public key is added to the target SSH server’s authorized_keys file, (and loaded to the SSH agent for resident keys), connecting is simple.

# SSH will automatically detect and use the YubiKey for authentication
ssh user@remote-server

# Explicitly specify the Yubikey-generated key
ssh -i ~/.ssh/id_ed25519_sk user@remote-server

# You'll be prompted to:
# 1. Enter your FIDO2 PIN (if verify-required was set)
# 2. Touch your YubiKey

Important Note for GNOME Users

By default, the GNOME Linux desktop environment uses its own SSH agent (SSH_AUTH_SOCK=/run/user/1000/gcr/ssh), which doesn’t work well with FIDO2 hardware keys. This usually results in a failure to authenticate with the error: sign_and_send_pubkey: signing failed for ED25519-SK "/home/user/.ssh/id_ed25519_sk" from agent: agent refused operation.

To fix this, just add the -o "IdentityAgent=none" option when connecting to the target machine. This bypasses the default GNOME agent to authenticate correctly.

# Connect in a GNOME Linux environment
ssh -o "IdentityAgent=none" -i ~/.ssh/id_ed25519_sk user@remote-server

# You'll be prompted to:
# 1. Enter your FIDO2 PIN (if verify-required was set)
# 2. Touch your YubiKey

This might look like a very long command just to connect to an SSH server, but you can specify these connection options in your SSH client config file ~/.ssh/config to avoid typing so much for every connection.

And that’s it, super simple and now you are more secure!


Delete Resident Keys From YubiKey

General YubiKey management commands are in Part. 1, to make this post more complete, I added them below.

List Resident Keys

# List resident keys in YubiKey
ykman fido credentials list

# Example output
Credential ID  RP ID  Username  Display name
5f85afc4...    ssh:   openssh   openssh    

Delete Resident Keys

# Delete a resident key from YubiKey by specifying its credential ID
# Delete resident key with credential ID "5f85afc4"
ykman fido credentials delete 5f85afc4


What’s Next?

Next post will be YubiKeys setup for GPG/PGP/PPP/GGG…