Securing SSH Authentication with FIDO2 Security Keys

Introduction: The Power of FIDO2 for SSH

Secure Shell (SSH) is a cornerstone of secure remote access and operations for developers. Traditionally, SSH relies on public-key cryptography, where private keys are stored as files on your computer. While secure, these files can be targets for theft or unauthorized access.

FIDO2 security keys, such as the YubiKey, strengthen SSH security by ensuring your private SSH keys never leave the hardware security key. This provides strong protection against malware, phishing, and remote attacks targeting your SSH credentials.

FIDO2 also requires user presence (a touch on your YubiKey) for cryptographic operations, and can optionally enforce user verification (PIN entry). These safeguards ensure that even if your workstation is compromised, attackers cannot use your SSH keys without your explicit physical approval.

This guide shows how to generate and use SSH keys directly on your FIDO2 security key with OpenSSH. It covers key generation, platform setup, GitHub integration, and security best practices.

Prerequisites

You will need:

  • A FIDO2 Security Key: Any YubiKey with FIDO2 support (YubiKey 5 Series, YubiKey Bio Series, Security Key Series by Yubico).

  • OpenSSH Client:

    • OpenSSH 8.2 or newer is required for FIDO2 hardware-backed keys.

    • OpenSSH 8.3 or newer is recommended for the verify-required option, which enforces user verification (PIN) for each operation.

  • YubiKey Manager: Required for setting or changing your FIDO2 PIN. Download it from the Yubico website.

Platform-Specific OpenSSH Setup

Check your OpenSSH version:

ssh -V

Update if necessary:

  • Linux:

    # Debian/Ubuntu
    sudo apt update && sudo apt install openssh-client
    
    # Fedora/RHEL/CentOS
    sudo dnf install openssh-clients
    
  • macOS:

    The bundled OpenSSH may be outdated. Install the latest with Homebrew:

    brew install openssh
    

    Update your PATH to prioritize the Homebrew version (/usr/local/bin or /opt/homebrew/bin).

  • Windows:

    Windows 10 (1809+) and Windows 11 include an OpenSSH client. Confirm with:

    Get-WindowsCapability -Online | ? Name -like 'OpenSSH.Client*'
    

    If missing, install via Settings > System > Optional features or with:

    Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
    

    For FIDO2 features, Windows Subsystem for Linux (WSL 2) often provides the best compatibility.

Setting or Changing Your FIDO2 PIN

For stronger security, set a FIDO2 PIN on your YubiKey:

  1. Insert your YubiKey.

  2. Open YubiKey Manager.

  3. Navigate to Applications > FIDO2.

  4. Select "Set PIN" (or "Change PIN").

  5. Follow the prompts to create a secure PIN.

The PIN will be required when generating resident keys and when user verification is enforced.

Generating Your FIDO2 SSH Key

You can generate two types of FIDO2-backed SSH keys:

  • ecdsa-sk: Supported on all FIDO2 YubiKeys.

  • ed25519-sk: Modern and preferred, requires YubiKey firmware 5.2.3+.

Generating an ed25519-sk Key (Recommended)

ssh-keygen -t ed25519-sk -O resident -O verify-required -C "your_email@example.com"

Generating an ecdsa-sk Key

Use if your YubiKey firmware is older than 5.2.3:

ssh-keygen -t ecdsa-sk -O resident -O verify-required -C "your_email@example.com"

Key Generation Options Explained

  • -t ed25519-sk or -t ecdsa-sk: Key type.

  • -O resident: Creates a resident key, stored on the YubiKey itself. Enables portability across machines. Requires a PIN.

  • -O verify-required: Requires both PIN entry and a physical touch for every use. (OpenSSH 8.3+).

  • -O application=ssh:<name>: Optional label if storing multiple SSH credentials.

  • -C "comment": Helps identify the key.

If you omit -O resident, a non-resident key is created. Its private key handle is stored on disk, but still requires user presence (touch). Use -O verify-required to enforce PIN verification.

The Key Generation Process

  1. Prompt to touch your YubiKey (user presence).

  2. If creating a resident key, prompt for your FIDO2 PIN (user verification).

  3. Choose a save location for the key handle file.

    • This file does not contain the private key—only a reference handle.

  4. Optionally set a local passphrase for the handle file.

The .pub file is your public key for servers or GitHub.

Adding Your FIDO2 SSH Key to the ssh-agent (Optional)

Unlike software keys, FIDO2 keys never export private key material. The file added with ssh-add is just a reference handle.

Key points:

  • ssh-agent remembers the reference, so you don’t need to re-specify the file.

  • The agent never caches your PIN—you’ll be prompted if verification is required.

  • A touch (presence) is always required unless -O no-touch-required was explicitly set.

To add your key:

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519_sk

You will be prompted for your PIN (if required) and to touch your YubiKey.

Integrating with GitHub (and other services)

  1. Copy your public key:

    # Linux
    cat ~/.ssh/id_ed25519_sk.pub | xclip -selection clipboard
    # macOS
    pbcopy < ~/.ssh/id_ed25519_sk.pub
    # Windows
    Get-Content $env:USERPROFILE\.ssh\id_ed25519_sk.pub | Set-Clipboard
    
  2. Add it in GitHub:

    • Go to Settings > SSH and GPG keys.

    • Select New SSH key.

    • Paste the key, label it, and save.

  3. Test:

    ssh -T git@github.com
    

    You should be prompted to touch your YubiKey (and enter your PIN if required).

Conceptual SSH FIDO2 Flow

Using Resident Keys on a New Machine

Resident keys allow portability. On a new machine:

  1. Ensure OpenSSH 8.2+ is installed.

  2. Insert your YubiKey and run:

    ssh-keygen -K
    

    This retrieves resident keys and creates handle and public key files. 3. Use normally or add to ssh-agent.

Troubleshooting

  • Permission denied / no prompt: Verify the correct public key is installed. Use ssh -vvv for debugging.

  • macOS issues: Install latest OpenSSH via Homebrew.

  • Unsupported key type / invalid format: Ensure OpenSSH 8.2+ (8.3+ for verify-required).

  • PIN issues: If forgotten, reset the FIDO2 application in YubiKey Manager. This deletes all FIDO2 credentials.

  • Multiple keys: Use ssh-keygen -K to list resident keys. Use -O application=ssh:<name> for clarity.

  • GitHub issues: See GitHub’s SSH troubleshooting guide.

Important Security Considerations

  • Protect your YubiKey physically. Consider a backup key.

  • Use a strong, unique PIN for FIDO2.

  • Avoid SSH agent forwarding (ssh -A) unless necessary. Forwarding exposes your keys’ usability to remote systems.

  • Secure your workstation. Keep it patched and monitored.

  • Protect non-resident key handle files. Use a passphrase and restrict file permissions.

Conclusion

Using a FIDO2 security key like the YubiKey for SSH authentication ensures your private keys remain hardware-bound and safe. By enforcing both user presence (touch) and user verification (PIN), you gain strong protection against credential theft and misuse.

Following this guide, you can confidently integrate YubiKeys with OpenSSH and GitHub, improving your security posture and reducing risks from common attacks.

Always consult the latest Yubico and OpenSSH documentation for updates and new capabilities.