Disclosure: As an Amazon Associate, CardWise earns from qualifying purchases at no additional cost to you. This does not affect our recommendations.
YubiKey PIV for SSH Authentication — Setup Walkthrough
Your SSH private key never has to live on disk. With a YubiKey 5 NFC, the RSA or ECC private key is generated inside the hardware security module and cannot be extracted. Every SSH authentication request is signed inside the YubiKey, and the signed response is sent to the server. Even if your laptop is compromised, the attacker cannot steal your SSH key.
This guide walks you through the complete setup: from a fresh YubiKey to SSH-ing into a server.
What You Need
- A YubiKey 5 NFC or YubiKey 5C NFC (FIDO2-only keys like Feitian BioPass or SoloKeys do not have PIV) Check Price on Amazon
ykman— Yubico's CLI management tool- OpenSSH 8.2+ (for native FIDO2) or any OpenSSH with PKCS#11 support
PIV Key Slots Overview
The YubiKey PIV application has several key slots. For SSH, we use the Authentication slot (9a):
| Slot | PIV ID | Typical Use |
|---|---|---|
| Authentication | 9a | SSH, login, general authentication |
| Digital Signature | 9c | Document signing, code signing |
| Key Management | 9d | Encryption, key exchange |
| Card Authentication | 9e | Card auth (less common) |
| Slots 82-95 | 82-95 | RSA/ECC (YubiKey 5.3+ firmware) |
Step 1: Set PIV PIN, PUK, and Management Key
A fresh YubiKey ships with default PIV credentials. Change them immediately:
# Set the PIN (default: 123456, min 6 digits, max 8 digits) ykman piv access change-pin --pin 123456 --new-pin YOUR_NEW_PIN # Set the PUK (default: 12345678, min 6 digits, max 8 digits) ykman piv access change-puk --puk 12345678 --new-puk YOUR_NEW_PUK # Set the management key (default: 010203040506070801020304050607080102030405060708) # Option A: Keep it derived from PIN (recommended — no separate key to remember) ykman piv access set-management-key --protect --pin YOUR_NEW_PIN # Option B: Set a custom management key (hex, 24 bytes) ykman piv access set-management-key --management-key 010203040506070801020304050607080102030405060708 --new-management-key YOUR_HEX_KEY
Step 2: Generate the PIV Key Pair
Generate an ECC or RSA key in slot 9a. The private key is generated inside the YubiKey and never leaves it.
# Option A: ECC P-256 (recommended — faster, smaller keys) ykman piv keys generate --algorithm ECCP256 --pin YOUR_NEW_PIN 9a # Option B: RSA 2048 (wider compatibility) ykman piv keys generate --algorithm RSA2048 --pin YOUR_NEW_PIN 9a
Step 3: Create a Self-Signed Certificate
SSH does not validate the certificate chain, but OpenSSH needs a certificate to extract the public key. Create a self-signed one:
ykman piv certificates generate --subject "SSH:[email protected]" --pin YOUR_NEW_PIN 9a
Step 4: Export the SSH Public Key
# Extract the SSH public key from the PIV certificate ssh-keygen -D /usr/lib/x86_64-linux-gnu/libykcs11.so > ~/.ssh/yubikey.pub # Or on macOS: ssh-keygen -D /usr/local/lib/libykcs11.dylib > ~/.ssh/yubikey.pub # Or using ykman directly: ykman piv export-ssh-key 9a > ~/.ssh/yubikey.pub
Copy the contents of ~/.ssh/yubikey.pub to the server's ~/.ssh/authorized_keys.
Step 5: Configure SSH to Use the YubiKey
Option A: PKCS#11 (universal, works with all OpenSSH)
# Add the YubiKey to ssh-agent ssh-add -s /usr/lib/x86_64-linux-gnu/libykcs11.so # Or on macOS: ssh-add -s /usr/local/lib/libykcs11.dylib # Test: ssh [email protected]
When you connect, you will be prompted for your PIV PIN. Enter it once, and the agent caches it for subsequent connections.
Option B: yubikey-agent (daemon, auto-starts with macOS/Linux)
# Install brew install yubikey-agent # macOS # Or: go install filippo.io/yubikey-agent@latest # Configure yubikey-agent --setup # Add to ssh config echo "IdentityAgent ~/Library/yubikey-agent/agent" >> ~/.ssh/config
yubikey-agent is a dedicated SSH agent that automatically loads your YubiKey PIV keys on startup. It prompts for PIN once per session.
Option C: FIDO2 resident key (OpenSSH 8.2+, no PIV needed)
# Generate a FIDO2 resident key directly ssh-keygen -t ed25519-sk -O resident -f ~/.ssh/id_ed25519_sk # Copy to server ssh-copy-id -i ~/.ssh/id_ed25519_sk.pub [email protected] # Connect (YubiKey will prompt for tap) ssh -i ~/.ssh/id_ed25519_sk [email protected]
This method uses FIDO2 instead of PIV. No PKCS#11 library needed, but requires OpenSSH 8.2+ on both client and server.
Multiple YubiKeys
If you have a backup YubiKey (recommended), generate keys on both and add both public keys to authorized_keys. A second YubiKey 5C NFC makes an ideal backup — different USB form factor so you are covered for both USB-A and USB-C ports. Check Price on Amazon
# Key 1 ykman piv export-ssh-key 9a >> ~/.ssh/authorized_keys # Switch to backup YubiKey, then: ykman piv export-ssh-key 9a >> ~/.ssh/authorized_keys
Each YubiKey has its own key pair, so the public keys are different.
Troubleshooting
| Problem | Solution |
|---|---|
| "device not found" when running ykman | Ensure YubiKey is inserted. Try a different USB port. Check ykman list |
| "wrong PIN" after 3 attempts | PUK can unlock: ykman piv access change-pin --puk YOUR_PUK |
| Both PIN and PUK blocked | Reset PIV: ykman piv reset (erases all keys) |
| SSH prompts for password, not YubiKey | Check ssh-add -l to verify the key is loaded in agent |
| libykcs11.so not found | Install yubico-piv-tool: brew install yubico-piv-tool or apt install libykcs11 |
Security Best Practices
- Always change default PIN/PUK from 123456 / 12345678
- Use a strong management key or derive it from PIN with
--protect - Have a backup YubiKey — generate separate keys on both and add both to
authorized_keys - Enable touch policy — require physical tap for every SSH signature:
ykman piv keys generate --touch-policy ALWAYS 9a - Disable SSH password auth on servers once YubiKey SSH is working
YubiKey Models Compared for SSH
| Feature | YubiKey 5 NFC | YubiKey 5C NFC | Feitian BioPass |
|---|---|---|---|
| PIV (SSH via PKCS#11) | Yes | Yes | No |
| FIDO2 (SSH via ed25519-sk) | Yes | Yes | Yes |
| OpenPGP | Yes | Yes | No |
| NFC | Yes | Yes | Yes |
| USB | USB-A | USB-C | USB-A |
| Biometric | No | No | Yes (fingerprint) |
YubiKey 5 NFC — Best for SSH with PIV support. Check Price on Amazon
YubiKey 5C NFC — USB-C variant for modern laptops. Check Price on Amazon