SSH Key Authentication
Key Takeaways
- SSH key auth proves identity by signing a challenge with the private key — the private key never leaves the client machine
- The server verifies the signature using the public key stored in authorized_keys — no secret is transmitted over the network
- ssh-agent caches decrypted private keys in memory so you don't re-enter the passphrase for every connection
- Agent forwarding is convenient but dangerous — a compromised intermediate host can use your forwarded agent to access other servers
SSH key authentication is the process by which an SSH client proves its identity to a server using a cryptographic key pair instead of a password. The client holds the private key; the server holds the corresponding public key. During authentication, the client signs a session-specific challenge with its private key, and the server verifies the signature using the stored public key. At no point does the private key or any reusable secret cross the network — making it immune to eavesdropping, replay attacks, and credential theft in transit.
Why it matters
- No secrets on the wire — unlike password auth (where the password is sent to the server, encrypted by TLS), key auth never transmits the private key. Even if TLS is somehow compromised, the credential isn’t exposed.
- Immune to server compromise — if the server is compromised, the attacker gets public keys (useless for impersonation). With password auth, a compromised server can capture passwords as users type them.
- Multi-factor capable — combine key auth with a passphrase (something you have + something you know) or hardware tokens (FIDO2/U2F) for true MFA on SSH.
- Automation-friendly — automated systems (CI/CD, cron jobs, configuration management) can authenticate without interactive password entry. The key file is the credential.
- Granular access control — authorized_keys supports per-key restrictions: forced commands, source IP limits, port forwarding restrictions, and environment variables.
How it works
- Client connects — TCP connection to server port 22, SSH protocol version exchange
- Key exchange — client and server perform ECDHE to establish encrypted channel (separate from user authentication)
- Server authentication — server presents its host key. Client verifies against
known_hosts(prevents MITM). - User authentication begins — server advertises supported auth methods (publickey, password, keyboard-interactive)
- Client offers public key — sends the public key fingerprint to check if the server recognizes it
- Server checks authorized_keys — looks up the public key in
~/.ssh/authorized_keysfor the target user - Challenge-response — server sends a challenge. Client signs it with the private key (decrypted from disk using passphrase, or from ssh-agent).
- Server verifies signature — if valid, authentication succeeds. Session begins.
In real systems
Server-side configuration (/etc/ssh/sshd_config):
# Enable key authentication, disable password
PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no
# Restrict authorized_keys location (prevent users from adding their own)
AuthorizedKeysFile /etc/ssh/authorized_keys/%u
# Allowed key types (restrict to modern algorithms)
PubkeyAcceptedAlgorithms ssh-ed25519,sk-ssh-ed25519@openssh.com,rsa-sha2-512
Per-key restrictions in authorized_keys:
# Force a specific command (key can only run backups)
command="/usr/local/bin/backup.sh",no-port-forwarding,no-X11-forwarding ssh-ed25519 AAAA... backup-key
# Restrict source IP
from="10.0.1.0/24,192.168.1.50" ssh-ed25519 AAAA... admin-key
# Time-limited (via external tooling — authorized_keys has no native expiry)
# Use SSH certificates instead for time-limited access
ssh-agent (key caching):
# Start agent and add key (passphrase entered once)
eval $(ssh-agent)
ssh-add ~/.ssh/id_ed25519
# Key cached in memory — subsequent SSH connections don't prompt for passphrase
# Add with timeout (key removed from agent after 1 hour)
ssh-add -t 3600 ~/.ssh/id_ed25519
# List cached keys
ssh-add -l
FIDO2/U2F hardware key (strongest option):
# Generate key backed by hardware security key (YubiKey, etc.)
ssh-keygen -t ed25519-sk -C "user@example.com"
# -sk = security key resident
# Requires physical touch of hardware key for every authentication
# Private key material never leaves the hardware token
Where it breaks
Agent forwarding to untrusted hosts — ssh -A forwards your ssh-agent to the remote host, allowing you to SSH from there to other servers using your local keys. But if the remote host is compromised, the attacker can use your forwarded agent to authenticate to any server your keys can access — for as long as your connection is open. Use ProxyJump (ssh -J) instead of agent forwarding: it routes through the intermediate host without exposing your agent.
Weak file permissions — SSH refuses to use a private key if its permissions are too open (chmod 644 instead of chmod 600). But authorized_keys with wrong permissions (world-writable home directory) silently fails — the server ignores the file and falls back to password auth. Users think key auth is working but it’s actually using passwords. Check: chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys.
Host key verification disabled — users add StrictHostKeyChecking no to their SSH config to avoid the “unknown host” prompt. This disables MITM protection entirely. An attacker performing DNS spoofing or ARP poisoning can present their own host key, and the client connects without warning. The first connection to a new host should verify the fingerprint out-of-band; subsequent connections are protected by known_hosts.
Operational insight
The security of SSH key authentication depends entirely on private key protection. The cryptography is unbreakable, but the private key is just a file on disk. If it’s unencrypted (no passphrase), anyone who can read the file has the credential. If it’s on a laptop that’s stolen, the attacker has it. If it’s in a Git repo (accidentally committed), it’s public. The strongest SSH key setup: Ed25519 key stored on a FIDO2 hardware token (YubiKey), requiring physical touch for each authentication. The private key never exists as a file — it’s generated and used entirely within the hardware. This eliminates every key theft vector: disk compromise, memory dump, backup exposure, and accidental sharing.
Related topics
Ready to Secure Your Enterprise?
Experience how our cryptographic solutions simplify, centralize, and automate identity management for your entire organization.