The short answer has not changed in years: use Ed25519. Since OpenSSH 9.5, ssh-keygen generates Ed25519 keys when you do not pass -t, so new keys already default to it. The longer answer matters when you manage a fleet that still has 2048-bit RSA keys from 2016, a switch that only speaks RSA, servers running in FIPS mode, or a security team asking what "post-quantum SSH" means for your keys.
This guide compares the key types OpenSSH supports today, explains the difference between a key type and a signature algorithm (the source of most "ssh-rsa is deprecated" confusion), and ends with a rotation plan. For server-side SSH hardening in general, see our SSH security best practices.
Key Types vs Signature Algorithms
A key type is the kind of key pair you hold. A signature algorithm is how that key signs the login challenge. For Ed25519 and ECDSA the two are the same thing. For RSA they are not, and that is where the confusion starts:
| Key type | Signature algorithms | Status in current OpenSSH |
|---|---|---|
ssh-ed25519 | ssh-ed25519 | Recommended default |
ecdsa-sha2-nistp256/384/521 | Same as the key type | Supported |
ssh-rsa | rsa-sha2-512, rsa-sha2-256 | Supported: same key, SHA-2 signatures |
ssh-rsa | ssh-rsa (SHA-1) | Disabled by default since OpenSSH 8.8 |
[email protected] | Same as the key type | Hardware FIDO2 key, OpenSSH 8.2+ |
[email protected] | Same as the key type | Hardware FIDO2 key, OpenSSH 8.2+ |
ssh-dss | ssh-dss | Removed entirely in OpenSSH 10.0 |
Your RSA key is not deprecated β what OpenSSH 8.8 disabled was the SHA-1 signature named ssh-rsa. The same RSA key signs with rsa-sha2-512 against any server from OpenSSH 7.2 onward. The public key line still starts with ssh-rsa, which is why people think it is affected.
See what your client supports β ssh -Q key lists key types, ssh -Q sig lists signature algorithms, and ssh -V shows the version they belong to.
Head to Head: Security, Speed, Compatibility
| Type | Approx. security | Key / signature size | Strengths | Weaknesses |
|---|---|---|---|---|
| Ed25519 | ~128-bit | 32-byte key, 64-byte signature | Fast, deterministic signatures, hard to implement wrongly | Needs OpenSSH 6.5+; restricted under some FIPS policies |
| ECDSA P-256 | ~128-bit | Small | Fast, NIST-approved, available in FIPS mode | Each signature needs a perfect random nonce |
| RSA 2048 | ~112-bit | 256-byte signature | Works everywhere | Minimum acceptable today; no reason to create new ones |
| RSA 3072 | ~128-bit | 384-byte signature | Universal compatibility at modern strength | Slower signing, large keys |
| RSA 4096 | Above 128-bit | 512-byte signature | Common policy requirement | Slowest signing; gains little in practice |
| Ed25519-sk / ECDSA-sk | As the base type | Small, plus hardware | Private key never leaves the token | Needs a FIDO2 token and OpenSSH 8.2+ on both ends |
Why Ed25519 wins β its signatures are deterministic: the nonce is derived from the key and the message, not from a random number generator. ECDSA's main historical failure mode, a weak or repeated nonce leaking the private key, cannot happen.
The ECDSA nonce problem is real β in 2024, PuTTY's P-521 implementation (CVE-2024-31497) generated biased nonces, and a few dozen signatures were enough to recover the private key. OpenSSH's ECDSA was not affected, but the design leaves no margin for error.
RSA size and speed β RSA verification is cheap but signing is expensive, and the cost grows steeply with key size. For an interactive login the difference is invisible; for automation making thousands of connections it is measurable.
Bigger RSA is not safer in the way that matters β a 4096-bit key does not make your laptop harder to steal or your passphrase harder to guess. The private key file is the attack surface, not the math.
Generating Each Type Correctly
# Ed25519: the default choice
$ ssh-keygen -t ed25519 -a 100 -C "alice@laptop 2026-10"
# RSA, only where something cannot use Ed25519
$ ssh-keygen -t rsa -b 4096 -a 100 -C "alice@laptop rsa 2026-10"
# ECDSA, mainly for FIPS-constrained environments
$ ssh-keygen -t ecdsa -b 256 -C "alice@laptop ecdsa"
# FIDO2 hardware key: touch required, PIN required, stored on the token
$ ssh-keygen -t ed25519-sk -O resident -O verify-required -O application=ssh:work
# On a new machine, pull resident keys back off the token
$ ssh-keygen -K
# Check what you have
$ ssh-keygen -lf ~/.ssh/id_ed25519.pub
256 SHA256:Q8m3nW0x2vJ5kTrd7yHq1pLcAe9ZbX4sFgUiNo6MKwE alice@laptop 2026-10 (ED25519)
-a sets KDF rounds β private keys are encrypted with your passphrase through bcrypt. -a 100 makes each passphrase guess much slower than the default of 16, at the cost of a slightly slower unlock. It does nothing without a passphrase.
Use the comment field β put the owner, device and date in -C. Months later, that comment is the only way to tell which line in authorized_keys belongs to a laptop that was lost.
Older tokens β some FIDO2 authenticators only support ECDSA. If ed25519-sk fails with a device error, use -t ecdsa-sk.
Passphrase plus agent β a passphrase protects the key file; ssh-agent or your desktop keyring means you type it once per session. Our SSH key setup guide walks through the full flow.
Audit and Enforce on Servers
Before you can retire weak keys you need to find them. ssh-keygen -l reads an authorized_keys file line by line and prints the size and type of every key in it:
$ ssh-keygen -lf ~/.ssh/authorized_keys
256 SHA256:Q8m3nW0x2vJ5kTrd7yHq1pLcAe9ZbX4sFgUiNo6MKwE alice@laptop 2026-10 (ED25519)
2048 SHA256:p1XvRk7cT0aBn4WqzUe8yHjLm2sDf5GoIc9VtNr3KbA deploy@ci-2019 (RSA)
# Every RSA key under 3072 bits on this host
$ sudo sh -c 'for f in /root/.ssh/authorized_keys /home/*/.ssh/authorized_keys; do
[ -f "$f" ] && ssh-keygen -lf "$f" | sed "s|^|$f |"
done' | awk '$NF=="(RSA)" && $2 < 3072'
# DSA keys: OpenSSH 10 cannot parse them any more, so grep for them
$ sudo grep -H 'ssh-dss' /root/.ssh/authorized_keys /home/*/.ssh/authorized_keys
# Host keys this server presents
$ for k in /etc/ssh/ssh_host_*_key.pub; do ssh-keygen -lf "$k"; done
Then restrict what the server accepts with a drop-in file:
# /etc/ssh/sshd_config.d/10-keytypes.conf
PubkeyAcceptedAlgorithms ssh-ed25519,[email protected],ecdsa-sha2-nistp256,rsa-sha2-512,rsa-sha2-256
HostKeyAlgorithms ssh-ed25519,ecdsa-sha2-nistp256,rsa-sha2-512,rsa-sha2-256
RequiredRSASize 3072
$ sudo sshd -t && sudo sshd -T | grep -iE 'pubkeyacceptedalgorithms|requiredrsasize'
$ sudo systemctl reload ssh # Debian/Ubuntu; the unit is sshd on RHEL/Fedora
First value wins β for most options, sshd uses the first value it reads. Drop-ins are read in name order, so a 10- file overrides a distribution file named 50-. Confirm the effective value with sshd -T.
RequiredRSASize needs OpenSSH 9.1 β it rejects RSA user and host keys below the given size. Debian 12 and Ubuntu 24.04 have it; RHEL 9 ships OpenSSH 8.7, where the system-wide crypto policy sets the RSA minimum instead (update-crypto-policies --set FUTURE requires 3072 bits).
Keep a session open β test a fresh login with each key type you still need before closing the session you changed the config from.
Build client entries β our SSH config generator writes per-host IdentityFile and IdentitiesOnly entries so the right key is offered to each server.
Compatibility Traps
| Situation | Symptom | What to do |
|---|---|---|
| New client, very old server or device that only knows SHA-1 ssh-rsa | no mutual signature algorithm | Re-enable ssh-rsa for that one host in ~/.ssh/config, not globally |
| Server older than OpenSSH 6.5 (for example CentOS 6) | Ed25519 key not accepted | Use RSA 3072+ for that host, and plan its replacement |
| Network switches, BMCs, embedded devices | Only RSA keys accepted | Keep a dedicated RSA key for device management |
| RHEL in FIPS mode | Ed25519 rejected by the crypto policy | Use ECDSA P-256/P-384 or RSA 3072+; check update-crypto-policies --show |
| Legacy DSA keys | Key ignored or unparseable on OpenSSH 10 | Replace them; there is no compatibility switch left |
# ~/.ssh/config: allow SHA-1 RSA for one legacy device only
Host old-switch
HostName 10.0.20.5
User admin
IdentityFile ~/.ssh/id_rsa_devices
IdentitiesOnly yes
HostKeyAlgorithms +ssh-rsa
PubkeyAcceptedAlgorithms +ssh-rsa
Scope it β putting +ssh-rsa under Host * weakens every connection to protect one device. Keep it inside the Host block for the device that needs it.
Hosted services β GitHub and GitLab accept Ed25519, ECDSA, RSA and FIDO2 security keys, and AWS EC2 key pairs support Ed25519 for Linux instances. There is rarely a platform reason to generate RSA for these.
Post-Quantum SSH and a Rotation Plan
Post-quantum SSH is about key exchange, not your keys. The threat is "harvest now, decrypt later": recording encrypted sessions today and decrypting them once a large quantum computer exists. Key exchange protects session confidentiality, so that is where OpenSSH added hybrid algorithms: [email protected] became the default in 9.0, and mlkem768x25519-sha256 became the default in 10.0. Recent releases also warn when a connection falls back to a non-post-quantum key exchange.
# Which key exchange did this connection use?
$ ssh -v server.example.com exit 2>&1 | grep 'kex: algorithm'
debug1: kex: algorithm: mlkem768x25519-sha256
# Rotate a user key without locking yourself out
$ ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519_2026 -C "alice@laptop 2026-10"
$ ssh-copy-id -i ~/.ssh/id_ed25519_2026.pub alice@server
$ ssh -i ~/.ssh/id_ed25519_2026 -o IdentitiesOnly=yes alice@server true && echo OK
$ ssh -i ~/.ssh/id_ed25519_2026 alice@server "sed -i.bak '/deploy@ci-2019/d' ~/.ssh/authorized_keys"
# Add an Ed25519 host key if an old server lacks one
$ sudo ssh-keygen -A # creates any missing default host key types
Authentication keys can wait β a signature only has to be unforgeable at the moment you log in. A future quantum computer cannot go back and log in to a session that already happened, so classical Ed25519 user keys remain fine for now. OpenSSH does not offer post-quantum signature keys yet.
Upgrade the software instead β the practical post-quantum step is running OpenSSH 9.0 or newer on both ends so a hybrid key exchange is negotiated. Old servers are the gap, not old keys.
Rotate on a schedule and on events β rotate keys when a device is lost or a person leaves, and at a regular interval for automation keys. Add the new key, test it, then delete the old line; never the other way round.
Host key changes β recent OpenSSH clients with UpdateHostKeys learn additional host keys from a server after a successful login, which lets you add an Ed25519 host key without every user seeing a changed-key warning. Remove the old host key only after clients have had time to learn the new one.
Frequently Asked Questions
Is Ed25519 better than RSA for SSH keys?
For almost every use, yes. Ed25519 offers about 128-bit security with a tiny key, signs faster than RSA, and uses deterministic signatures that do not depend on a random number generator at signing time. Use RSA 3072 or larger only for systems that cannot accept Ed25519, such as very old servers or some network devices.
Is ssh-rsa deprecated? Do I need to replace my RSA key?
OpenSSH 8.8 disabled the ssh-rsa signature algorithm, which uses SHA-1. RSA keys themselves still work and sign with rsa-sha2-256 or rsa-sha2-512 against any server from OpenSSH 7.2 onward. Replace RSA keys smaller than 3072 bits as part of normal rotation, and prefer Ed25519 for new keys.
Should I use ECDSA or Ed25519?
Prefer Ed25519. ECDSA is secure when implemented correctly, but every signature depends on a perfectly random nonce, and implementation mistakes have leaked private keys in the past. ECDSA P-256 or P-384 is the right choice mainly where a FIPS policy does not allow Ed25519.
Are FIDO2 ed25519-sk keys worth it?
For administrators and anyone with access to production, yes. The private key stays on the hardware token, so malware on the laptop cannot copy it, and each login needs a physical touch. Both client and server need OpenSSH 8.2 or newer, and older tokens may only support ecdsa-sk.
Do I need post-quantum SSH keys in 2026?
Not yet. The urgent post-quantum risk is recorded traffic being decrypted later, which is handled by key exchange. OpenSSH 9.0 and newer negotiate hybrid post-quantum key exchange by default, and 10.0 defaults to mlkem768x25519-sha256. Keep OpenSSH current on both ends; existing Ed25519 keys are still appropriate for authentication.