Use FIDO2 Security Keys for SSH Authentication
OpenSSH security-key credentials (ecdsa-sk or ed25519-sk) use a FIDO authenticator to sign SSH challenges. The local .pub file is public; the local private-key handle is still needed, while the signing secret remains on the authenticator. A copied handle alone cannot authenticate without the registered hardware key.
A touch proves user presence. Requiring a PIN or biometric adds authenticator user verification, but SSH security-key login is not automatically multi-factor authentication in every policy or threat model. It does not protect a compromised client or replace host-key verification. This guide requires touch and user verification, uses two separately enrolled keys, and only then disables password-based SSH login.
Step 1: Check OpenSSH and Authenticator Support
Confirm the Client Supports Security-Key Algorithms
Client PreparationUse an OpenSSH client with FIDO security-key support and an authenticator that supports user verification. Check for an sk- key algorithm before creating a credential. Win32 OpenSSH support is available in version 8.9.0.0 and later; no vendor key-manager application is required for OpenSSH authentication.
ssh -Vssh.exe -Vssh.exe -Q key | findstr /i "sk-ssh-ed25519 sk-ecdsa-sha2-nistp256"❯ View Expected Console Output
OpenSSH_9.xStep 2: Create Two Independently Enrolled Keys
Generate a Primary Key and a Backup-Key Credential
Authenticator SetupUse a separate FIDO authenticator for the backup. Generate a credential for each device and protect each local key-handle file with a passphrase and appropriate file permissions. Keep the existing administrator session open while setting up and testing both credentials. If your authenticator cannot perform user verification, the verify-required option will fail; use a supported authenticator rather than removing the server requirement.
mkdir -p ~/.ssh && chmod 700 ~/.sshssh-keygen -t ecdsa-sk -O verify-required -f ~/.ssh/id_ecdsa_sk_primary -C "admin-primary-key"ssh-keygen -t ecdsa-sk -O verify-required -f ~/.ssh/id_ecdsa_sk_backup -C "admin-backup-key"chmod 600 ~/.ssh/id_ecdsa_sk_primary ~/.ssh/id_ecdsa_sk_backup$sshDir = Join-Path $env:USERPROFILE '.ssh'New-Item -ItemType Directory -Force -Path $sshDir | Out-Nullssh-keygen.exe -t ecdsa-sk -O verify-required -f (Join-Path $sshDir 'id_ecdsa_sk_primary') -C 'admin-primary-key'ssh-keygen.exe -t ecdsa-sk -O verify-required -f (Join-Path $sshDir 'id_ecdsa_sk_backup') -C 'admin-backup-key'❯ View Expected Console Output
Generating public/private ecdsa-sk key pair.Enter PIN for authenticator:You may need to touch your authenticator to authorize key generation.Your identification has been saved in .../id_ecdsa_sk_primaryYour public key has been saved in .../id_ecdsa_sk_primary.pubStep 3: Enroll and Test Both Keys Before Hardening
Install Both Public Keys and Verify New Sessions
Access ValidationAdd both public keys to the target account while the current administrative session remains open. Use the matching client commands below, then connect once with each authenticator and confirm the PIN or biometric and touch prompt succeeds. Do not continue until both credentials work and you have a separate recovery path approved by your organization.
cat ~/.ssh/id_ecdsa_sk_primary.pub | ssh [email protected] 'umask 077; mkdir -p ~/.ssh; chmod 700 ~/.ssh; touch ~/.ssh/authorized_keys; chmod 600 ~/.ssh/authorized_keys; IFS= read -r key; if ! grep -qxF "$key" ~/.ssh/authorized_keys; then printf "%s\n" "$key" >> ~/.ssh/authorized_keys; fi'cat ~/.ssh/id_ecdsa_sk_backup.pub | ssh [email protected] 'umask 077; mkdir -p ~/.ssh; chmod 700 ~/.ssh; touch ~/.ssh/authorized_keys; chmod 600 ~/.ssh/authorized_keys; IFS= read -r key; if ! grep -qxF "$key" ~/.ssh/authorized_keys; then printf "%s\n" "$key" >> ~/.ssh/authorized_keys; fi'
# Test each key in a separate new session; the second command uses the backup authenticator.$sshDir = Join-Path $env:USERPROFILE '.ssh'$primaryPublicKey = (Get-Content -Raw (Join-Path $sshDir 'id_ecdsa_sk_primary.pub')).Trim()$backupPublicKey = (Get-Content -Raw (Join-Path $sshDir 'id_ecdsa_sk_backup.pub')).Trim()$primaryPublicKey | ssh.exe [email protected] 'umask 077; mkdir -p ~/.ssh; chmod 700 ~/.ssh; touch ~/.ssh/authorized_keys; chmod 600 ~/.ssh/authorized_keys; IFS= read -r key; if ! grep -qxF "$key" ~/.ssh/authorized_keys; then printf "%s\n" "$key" >> ~/.ssh/authorized_keys; fi'$backupPublicKey | ssh.exe [email protected] 'umask 077; mkdir -p ~/.ssh; chmod 700 ~/.ssh; touch ~/.ssh/authorized_keys; chmod 600 ~/.ssh/authorized_keys; IFS= read -r key; if ! grep -qxF "$key" ~/.ssh/authorized_keys; then printf "%s\n" "$key" >> ~/.ssh/authorized_keys; fi'
# Test each key in a separate new session.❯ View Expected Console Output
Authenticated with ecdsa-sk key; user verification and touch completed.Keep the original administrator session open until both test logins succeed.Step 4: Require Security-Key Authentication on the Linux Server
Restrict Accepted Keys and Require User Verification
Server HardeningConfirm your server’s OpenSSH version supports these directives and that all affected administrator accounts have both keys enrolled. The settings below accept only OpenSSH security-key algorithms, require user presence and verification, and disable password and keyboard-interactive authentication. Check the effective values with sshd -T; if they differ, resolve the configuration include or Match precedence before reloading. Keep your current session and an out-of-band recovery route available while applying the change.
sudo install -d -m 0755 /etc/ssh/sshd_config.dsudo tee /etc/ssh/sshd_config.d/99-security-key-only.conf >/dev/null <<'EOF'PubkeyAcceptedAlgorithms [email protected],[email protected]PubkeyAuthOptions touch-required,verify-requiredAuthenticationMethods publickeyPasswordAuthentication noKbdInteractiveAuthentication noEOF
# Validate syntax and inspect the effective global settings before reloading.sudo sshd -tsudo sshd -T | grep -E '^(pubkeyacceptedalgorithms|pubkeyauthoptions|authenticationmethods|passwordauthentication|kbdinteractiveauthentication) '❯ View Expected Console Output
pubkeyacceptedalgorithms [email protected],[email protected]pubkeyauthoptions touch-required,verify-requiredauthenticationmethods publickeypasswordauthentication nokbdinteractiveauthentication noChoose the service name for your distribution, then reload the daemon:
sudo systemctl reload sshsudo systemctl reload sshdStep 5: Confirm the New Policy and Keep Recovery Available
Open Fresh Sessions with Both Keys
Final VerificationFrom a second terminal, open a new session with the primary key and then the backup key. Confirm that each requires the intended verification and touch. Only close the original session after both logins succeed and the recovery path is confirmed. Repeat the review for every account affected by the server-wide policy.
$sshDir = Join-Path $env:USERPROFILE '.ssh'❯ View Expected Console Output
Both newly opened sessions authenticated with their separately enrolled security keys.Password and keyboard-interactive SSH authentication are disabled by the effective server policy.