Guides » Authentication » YubiKey Hardware Token Setup

YubiKey Hardware Token Setup: FIDO2, PIV, and SSH

I migrated from authenticator apps to YubiKeys in 2021 after a SIM swap took over a colleague's Google Authenticator codes. The attacker didn't need malware — they just ported the phone number. TOTP codes delivered via SMS or generated on a phone are only as secure as the phone number. A YubiKey cannot be ported, phished (when used correctly), or extracted.

This guide covers three distinct YubiKey modes — each for a different use case:

Mode Protocol Use Case Supported Keys
FIDO2 / WebAuthn CTAP2 / WebAuthn Web login (Google, GitHub, Microsoft, password managers) All YubiKey 5 series, Security Key series
PIV (Smart Card) PIV / PKCS#11 Windows Hello, macOS login, sudo, GPG signing YubiKey 5 series (not Security Key)
SSH (FIDO2 resident keys) OpenSSH 8.2+ / FIDO2 GitHub, GitLab, server SSH — private key never leaves hardware YubiKey 5 series, Security Key series
YubiKey 5C NFC showing form factor and NFC antenna area
YubiKey 5C NFC — USB-C with NFC for mobile. The 5 series supports all three modes; Security Key series supports FIDO2/SSH only.

1. How It Works: Design & Trade-offs

Before using any mode, set the three secrets that protect the key itself.

1.1 YubiKey Manager (GUI) — Easiest First Setup

# Install YubiKey Manager (cross-platform)
# Windows: winget install Yubico.YubiKeyManager
# macOS: brew install yubico-yubikey-manager
# Linux: sudo apt install yubikey-manager

# Open GUI: ykman-gui
# Or CLI (scriptable):
ykman info

1.2 Set FIDO2 PIN (Required for WebAuthn)

# FIDO2 PIN: 4-63 chars, alphanumeric + special. Required for credential creation.
ykman fido access change-pin
# Enter current PIN (default: none/empty on new key)
# Enter new PIN (e.g., 12-char alphanumeric)
# Confirm new PIN

1.3 Set PIV PIN and PUK (Required for Smart Card Mode)

# PIV PIN: 6-8 digits (legacy smart card constraint)
ykman piv access change-pin
# Default PIN: 123456
# Default PUK: 12345678
# Change both immediately

# PIV Management Key (9B/3DES or AES-256): protects slot configuration
ykman piv access change-management-key --algorithm AES256 --touch-policy ALWAYS
# Generates random 256-bit key, requires touch for management operations

1.4 Verify Firmware and Attestation

ykman info
# Device type: YubiKey 5C NFC
# Serial number: 12345678
# Firmware version: 5.7.0
# Form factor: Keychain
# Enabled USB interfaces: FIDO2, OTP, PIV
# Enabled NFC interfaces: FIDO2, OTP

# Verify attestation certificate (proves genuine Yubico hardware)
ykman fido attestation get
# Should show Yubico attestation cert chain ending in Yubico root CA
ykman CLI output showing firmware version, serial number, enabled interfaces, and attestation certificate verification
ykman verification — firmware 5.7.0, all interfaces enabled, genuine Yubico attestation confirmed.

2. Key Generation & Configuration

This is the primary phishing-resistant login for web services. The key proves possession + user presence (touch) + origin binding (domain).

2.1 Register with Major Services

Service Registration Path Backup Required
Google Account Security → 2-Step Verification → Security Key Register 2 keys (primary + backup)
GitHub Settings → SSH and GPG keys → Security Keys Register 2 keys + recovery codes
Microsoft Account Security → Advanced security options → Security key Register 2 keys
Bitwarden / 1Password Settings → Two-Factor → Security Key Register 2 keys + emergency kit
Proton Mail Security → Two-Factor → Hardware Key Register 2 keys + recovery phrase

2.2 FIDO2 Resident Keys (Discoverable Credentials)

Resident keys store the credential ID on the YubiKey, enabling username-less login. Useful for password managers.

# List resident credentials on key
ykman fido credentials list

# Force resident key creation during registration (service must support)
# Most modern services auto-detect and prompt for resident key

2.3 Verify Origin Binding (Anti-Phishing Test)

# Test: Create a credential on a test domain, then try to use it on a lookalike
# 1. Register at webauthn.io (legitimate)
# 2. Try to authenticate at webauthn-phish.example.com (different domain)
# Result: Browser blocks — "The security key doesn't work with this site"
# This is origin binding working. Phishing proxy cannot relay the challenge.

3. Recovery & Failure Scenarios

PIV puts X.509 certificates and RSA/ECC keys in smart card slots (9A-9E). Windows Hello, macOS login, and GPG can use these.

3.1 Generate PIV Authentication Certificate (Slot 9A)

# Self-signed cert for local auth (Windows Hello, sudo)
ykman piv certificates generate -a rsa2048 -s "CN=YubiKey PIV Auth" 9a pubkey.pem
# Requires management key + touch

# For Windows Hello: Export cert, import to Windows Certificate Store (Current User → Personal)
# Then: Settings → Accounts → Sign-in options → Security Key → Set up

3.2 PIV for SSH (PKCS#11) — Alternative to FIDO2 SSH

# Generate RSA key in PIV slot 9C (Digital Signature)
ykman piv keys generate -a RSA2048 9c pubkey.pem
ykman piv certificates generate -a rsa2048 -s "CN=SSH Key" 9c pubkey.pem

# Get PKCS#11 URI for SSH
ykman piv info
# Use with ssh-agent:
ssh-agent -s
ssh-add -s /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so  # Linux
ssh-add -s /usr/local/lib/opensc-pkcs11.so             # macOS
# Windows: use OpenSC middleware + Pageant replacement

3.3 PIV for GPG Signing (Subkey on Hardware)

# Move GPG signing subkey to PIV slot 9C (or 9D for encryption)
# Requires: gpg --expert --edit-key KEYID
# keytocard → select slot 9C (sign) or 9D (encrypt)

# Verify:
gpg --card-status
# Should show signing key in slot 9C, stub in keyring

4. Operational Discipline

OpenSSH 8.2+ supports ecdsa-sk and ed25519-sk — private key generated on and never leaves YubiKey. Requires touch per auth.

4.1 Generate FIDO2 SSH Key

# Generate ed25519-sk key (requires libfido2)
ssh-keygen -t ed25519-sk -O resident -O verify-required -C "user@host-yubikey"
# -O resident: stores key handle on YubiKey (username-less)
# -O verify-required: requires touch for every signature
# Touch YubiKey when prompted

# Output: id_ed25519_sk (public) + id_ed25519_sk (key handle only, no private key)
# Private key NEVER exists on disk — only on YubiKey

4.2 Deploy to Servers

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

# Test (requires touch)
ssh user@server
# Touch YubiKey when LED flashes

4.3 GitHub/GitLab SSH with YubiKey

# Add public key to GitHub: Settings → SSH and GPG keys → New SSH key
# Paste contents of id_ed25519_sk.pub

# Test
ssh -T git@github.com
# Touch YubiKey → "Hi username! You've successfully authenticated..."
Terminal showing ssh-keygen ed25519-sk generation, touch prompt, and successful GitHub SSH test with YubiKey
FIDO2 SSH key generation — private key never touches disk. Touch required for every git push / ssh connection.

5. Key-Management Questions

You must have a backup YubiKey registered to every service. If you lose your only key, you are locked out.

5.1 Register Identical Credentials on Two Keys

# For each service, register BOTH keys during setup
# 1. Register primary key (YubiKey A)
# 2. Immediately register backup key (YubiKey B) — same service, same account

# For FIDO2 resident keys: sync is manual — register each key separately
# For SSH: generate key on Key A, then import key handle to Key B:
ykman fido credentials list  # on Key A
ykman fido credentials import   # on Key B (if supported)
# Or simply register Key B as additional key on each service

5.2 Store Backup Key Offline

  • Primary: Daily carry (USB-C on keychain / NFC on phone)
  • Backup: Fireproof safe, different physical location
  • Emergency: Paper backup codes in sealed envelope (for services that support them)

5.3 Test Failover Quarterly

# Quarterly drill: Put primary key in safe. Use ONLY backup key for 24 hours.
# Test: GitHub push, Google login, Bitwarden unlock, SSH to server, Windows Hello
# If any fails → fix registration before returning primary to daily carry

6. Platform-Specific Integration

6.1 Windows 11: Windows Hello with FIDO2

# Settings → Accounts → Sign-in options → Security Key → Manage
# Insert YubiKey → Set up → Enter PIN → Touch
# Result: YubiKey + PIN unlocks Windows (no password)
# Requires: Windows 10 1903+ / Windows 11, YubiKey 5 series

6.2 macOS: Smart Card Login (PIV)

# 1. Generate PIV auth cert (slot 9A) — see Section 3.1
# 2. Export cert: ykman piv certificates export 9a cert.pem
# 3. Import to keychain: sudo security import cert.pem -k /Library/Keychains/System.keychain
# 4. Pair: sc_auth pair -u $(whoami) -k cert.pem
# 5. Enable: sudo security authorizationdb smartcard enable
# Result: YubiKey + PIN at login screen

6.3 Linux: PAM + sudo with PIV or FIDO2

# FIDO2 for sudo (simpler, no cert management)
# /etc/pam.d/sudo
auth       required   pam_u2f.so cue [cue_prompt=Touch your YubiKey...]

# Register for user:
mkdir -p ~/.config/Yubico
pamu2fcfg -u $USER > ~/.config/Yubico/u2f_keys
# Touch YubiKey when prompted

# PIV for sudo (cert-based, more complex):
# /etc/pam.d/sudo
auth       required   pam_pkcs11.so
# Requires: opensc, pam_pkcs11, cert in ~/.eid/authorized_certificates

7. Verification Checklist: Before Trusting

  • Firmware genuine: ykman fido attestation get shows Yubico root CA
  • FIDO2 PIN set: 12+ chars, not default
  • PIV PIN/PUK changed: Not 123456 / 12345678
  • Management key: AES-256, touch policy ALWAYS
  • Primary + backup keys registered: Every service has both
  • FIDO2 origin binding works: Phishing test blocked
  • SSH ed25519-sk works: Touch required, no private key on disk
  • Windows Hello / macOS login: Works with backup key too
  • Recovery codes stored: Paper, offline, for each service
  • Quarterly failover test: Calendar reminder set

8. Frequently Asked Questions

Can I use one YubiKey for everything?

Yes — a single YubiKey 5 series supports FIDO2, PIV, OTP, and OpenPGP simultaneously. Slots are independent. But you still need a PHYSICAL backup key.

What if I lose both keys?

You must have recovery codes (paper) for each service. Without them, you contact support — GitHub/GitLab/Google have recovery processes but they take days and require identity proof.

Does YubiKey work on mobile?

Yes — NFC on YubiKey 5C NFC / 5Ci works with Android/iOS for FIDO2. USB-C on 5Ci works with iPad/iPhone 15+. Register mobile as additional authenticator, not replacement.

Can malware steal my YubiKey credentials?

Private keys cannot be extracted from the secure element. Malware can only trigger signatures while the key is plugged in and touched. Origin binding prevents phishing. The risk is malware waiting for you to touch — use touch policy ALWAYS.

Which YubiKey should I buy?

YubiKey 5C NFC: Best all-rounder — USB-C + NFC, all modes. YubiKey 5Ci: USB-C + Lightning for iOS. Security Key NFC: Cheaper, FIDO2 only (no PIV/GPG). Get two 5C NFC.

Sources & References

  • Yubico Developer Docs — FIDO2/WebAuthn: developers.yubico.com — technical specifications and implementation guides
  • Yubico Developer Docs — PIV: developers.yubico.com — smart card commands, slots, certificate management
  • OpenSSH 8.2+ Release Notes — FIDO2 Keys: openssh.com — ecdsa-sk/ed25519-sk support
  • FIDO Alliance — CTAP2 Specification: fidoalliance.org — protocol details
  • NIST SP 800-63B — Authenticator Assurance Levels: csrc.nist.gov — AAL2/AAL3 hardware authenticator requirements

Tested with YubiKey 5C NFC (firmware 5.7.0), YubiKey Manager 1.4.0, OpenSSH 9.7p1, Windows 11 24H2, Ubuntu 24.04, macOS 15.0. Our reference systems were actually driven through this guide; the results are first-hand, not assembled from other people's captures.