ssh-keygen -t ed25519: Which SSH Key Type to Use
· by Andergrove Software
The short version, for anyone who came here to copy a command:
ssh-keygen -t ed25519 -C "you@example.com"
That is the right answer for essentially every new key in 2026. What follows is why it is the right answer, what the alternatives actually cost you, and the part most posts skip: what a quantum computer would and would not do to the key you just made.
You can build the command with the options filled in, or generate a key entirely in your browser, with the SSH key generator.
The command, flag by flag
-t ed25519picks the key type. On OpenSSH 9.5 and later you can leave it off entirely — baressh-keygenproduces Ed25519 now, having defaulted to RSA for the previous two decades. Typing it anyway is free and makes the intent obvious to whoever reads your notes later.-C "you@example.com"is just a label stored in the key file. It has no cryptographic role whatsoever; it exists so thatauthorized_keyson a shared server is not six anonymous blobs. An email is conventional;laptop-2026is more useful.-f ~/.ssh/id_ed25519_githubwrites somewhere other than the default, which is how you keep separate keys per host.-a 100raises the number of KDF rounds protecting your passphrase on disk. The default is 16. If someone steals the file, this is the difference between guessing quickly and guessing slowly.-N ""sets an empty passphrase. Useful in automation, a bad habit on a laptop.
You will be asked for a passphrase and a file location. Both prompts have sensible defaults, which is why so many people press Enter three times and never think about SSH keys again.
The four key types, and which are still alive
Ed25519 is an EdDSA signature scheme over Curve25519, in OpenSSH since 6.5 in 2014. It has one parameter set, so there is nothing to configure and nothing to get wrong. Keys are 32 bytes; the public key fits on one line with room to spare. Signing and verifying are fast, and the design deliberately avoids the sharp edges that have historically cut ECDSA implementations.
ECDSA (-t ecdsa, curves P-256/384/521) is fine cryptography with an unfortunate operational property: each signature needs a unique random nonce, and reusing one leaks the private key outright. That is not theoretical — it is how the PlayStation 3 signing key was recovered in 2010. OpenSSH's implementation is careful, so this is an argument about ecosystem risk rather than a live bug, but there is no upside to compensate for it.
RSA (-t rsa) still works everywhere and is the right choice for exactly one situation: a server too old to speak Ed25519. Use 3072 bits (the ssh-keygen default) or 4096. A 4096-bit public key is roughly 740 characters against Ed25519's 68, and generating one takes noticeably longer. Note that RSA the key is fine; it was RSA with SHA-1 signatures that got deprecated, which is why some ancient keys stopped working on Git hosts a few years back.
DSA is dead. Capped at 1024 bits, disabled by default since OpenSSH 7.0, and removed from the codebase entirely in OpenSSH 10. If you find one in an authorized_keys file, you have found a machine that needs attention for other reasons too.
There is also a fifth option worth knowing: -t ed25519-sk, added in OpenSSH 8.2, which keeps the private half inside a FIDO2 security key. The file on your disk is useless without the physical token, which is about as close as SSH gets to unstealable credentials.
How they actually compare
| Type | Security level | Public key | Verdict |
|---|---|---|---|
ed25519 | ~128-bit | 68 chars | The default. Use it. |
ecdsa P-256 | ~128-bit | ~180 chars | Works; no reason to prefer it. |
rsa 3072 | ~128-bit | ~570 chars | For legacy servers. |
rsa 4096 | ~150-bit | ~740 chars | Marginal gain, real cost. |
dsa | broken | — | Never. |
Note how little the "security level" column varies among the living options. Ed25519 and RSA 3072 both sit at roughly 128 bits, which is far beyond brute force. Nobody is going to factor your key. They are going to read it off a backup you forgot about, or find it in a repository, or watch you paste it. Key type is one of the least important variables in your actual security; it is just the one with a command to copy.
What quantum computing changes, and what it does not
Here is where the honest answer is more interesting than the scary one. Shor's algorithm, run on a sufficiently large fault-tolerant quantum computer, breaks RSA and elliptic-curve cryptography, including Ed25519. Choosing Ed25519 over RSA 4096 buys you exactly nothing against that threat. Neither is post-quantum. Anyone selling "quantum-resistant SSH keys" today is selling something that does not exist in OpenSSH.
But the two halves of an SSH connection face very different risks, and conflating them is the usual mistake.
Key exchange protects confidentiality, and that is the urgent half. An adversary can record your encrypted session today and decrypt it years later once the hardware exists — "harvest now, decrypt later." That risk is real for anything with a long secrecy lifetime, and it is why OpenSSH moved first here: 9.0 made the hybrid sntrup761x25519-sha512 the default key exchange back in 2022, 9.9 added an ML-KEM-based hybrid, and 10.0 made mlkem768x25519-sha256 the default. These are hybrids: they combine a post-quantum KEM with classical X25519, so the session stays safe if either component holds. If your OpenSSH is current on both ends, your session confidentiality is already post-quantum, and you did not have to do anything.
Authentication keys are signatures, and signatures are not harvestable. Recording a login today gives an attacker nothing to decrypt later — the signature proved who you were at that moment and then stopped being useful. A future quantum computer could forge your signature, but only from the day it exists, and only if that key is still trusted. The remedy is rotation, and rotation is something you should be doing anyway.
NIST standardised its post-quantum signature schemes in 2024 (ML-DSA in FIPS 204, SLH-DSA in FIPS 205), but OpenSSH does not yet offer them as user or host key types. When it does, changing over will be one ssh-keygen invocation and one paste into authorized_keys — the same three minutes it took the first time. That is the actual reason not to lose sleep: SSH key material is cheap to replace, which is the whole point of a system where the public half is the only thing you ever have to distribute.
Using the key for Git access
Git over SSH is the most common reason anyone runs ssh-keygen at all. Add the public key — the .pub file, never the other one — to GitHub under Settings → SSH and GPG keys, or the equivalent on GitLab, Bitbucket or your own Forgejo. Then check it:
ssh -T git@github.com
# Hi username! You've successfully authenticated...
GitHub accepts Ed25519, ECDSA and RSA (with SHA-2 signatures), plus the -sk hardware variants. It dropped DSA long ago and disabled SHA-1 RSA signatures in March 2022. If an old key stopped working around then, that is why, and the fix is a new Ed25519 key rather than an argument with the error message.
Once you have more than one key — a work account and a personal one, say — stop passing -i by hand and write it down once in ~/.ssh/config:
Host github.com
User git
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
Then git clone git@github-work:org/repo.git picks the right key automatically. IdentitiesOnly yes matters more than it looks: without it, ssh offers every key in your agent in turn, and a server that only allows a few attempts can lock you out before reaching the correct one.
The same key can also sign your commits, which is a nice consolidation if you never got on with GPG:
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true
Using the key for SFTP
SFTP is not a separate protocol with its own credentials — it is a subsystem running inside an SSH connection. That means the key you just made already works for it, and everything above about types and passphrases applies unchanged. Install the public key on the server and connect:
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host
sftp user@host
sftp -i ~/.ssh/id_ed25519_backup user@host # a specific key
Where SFTP genuinely differs is what you should do after the key works. File transfer accounts are usually automation, and automation keys usually have no passphrase, which makes them the most likely credential on the box to end up somewhere it should not be. So constrain what the key can do, in authorized_keys, on the line before the key itself:
restrict,command="internal-sftp",from="203.0.113.0/24" ssh-ed25519 AAAAC3Nza... backup@ci
restrict switches off port forwarding, agent forwarding, X11 and PTY allocation in one word — and, usefully, keeps disabling new things as OpenSSH adds them. command="internal-sftp" means that key can transfer files and cannot get a shell, no matter what the client asks for. from= pins it to the addresses your CI actually uses. On the server side, ForceCommand internal-sftp plus ChrootDirectory in a Match Group sftp-only block does the same job for a whole class of accounts.
This is the part worth spending effort on. An unconstrained automation key is a shell on your server that nobody is watching.
The habits that matter more than the key type
- Use a passphrase, and let
ssh-agenthold the decrypted key so you type it once a session. An unencrypted private key is a password file with extra steps. - Fix the permissions.
chmod 600 ~/.ssh/id_ed25519. OpenSSH will refuse a world-readable private key, which is the one time it protects you from yourself. - Generate keys where they will live. A private key that travels between machines has more copies than you can account for.
- Never forward your agent to a host you do not control. Root on that box can use your agent to authenticate as you, anywhere.
ProxyJumpsolves the same problem without handing over the keys. - Rotate. Not on a nervous schedule, but when someone leaves, when a laptop is replaced, and when you cannot remember where a key has been. Rotation is also your entire post-quantum migration plan, which makes it cheaper than it sounds.
So: Ed25519, then
Run ssh-keygen -t ed25519 -C "you@example.com", give it a passphrase, add the .pub to your Git host and your servers, and spend the time you saved on constraining what your automation keys are allowed to do. That last part is where the actual risk lives — not in whether you picked 4096 bits.