
September 11, 2026
12 min read
By Kokil Thapa | Last reviewed: September 2026
Choosing between RSA vs Ed25519 for keys shows up the moment you generate an SSH key, sign a JWT, or configure a CI deploy secret. RSA has been the default for decades and still works almost everywhere. Ed25519 is smaller, faster, and harder to misconfigure, but older clients and some enterprise tools reject it. This guide compares both algorithms with copy-paste commands, a decision table, and migration steps drawn from production Linux server administration and SSH key-only authentication work.
What is the difference between RSA and Ed25519 for cryptographic keys?
RSA and Ed25519 solve the same problem—public-key cryptography—but with different math and trade-offs. RSA relies on the difficulty of factoring large integers. Ed25519 is an Edwards-curve signature scheme defined in RFC 8032. You get a fixed 256-bit private key and a 512-byte signature.
RSA key sizes vary. A 2048-bit RSA key was once standard. Security guidance now treats 2048-bit RSA as a sunset size. A 4096-bit RSA key is safer but produces larger signatures and slower operations. Ed25519 keys are always 256 bits. There is no "pick a size" step that teams get wrong.
Both algorithms provide digital signatures. Neither is a drop-in replacement for symmetric encryption like AES. You sign with a private key and verify with a public key. That pattern powers SSH host authentication, Git deploy keys, JWT bearer tokens, and TLS certificate chains.
The practical gap is ecosystem age. RSA predates cloud-native tooling by decades. Ed25519 arrived in OpenSSH 6.5 and is now the default in current OpenSSH releases documented at openssh.com. If your stack is Ubuntu 22.04 or 24.04 with current packages, Ed25519 support is already there.
Side-by-side numbers that matter in production
| Criteria | RSA (4096-bit) | Ed25519 | Verdict |
|---|---|---|---|
| Private key size (PEM, typical) | ~3.2 KB | ~400 bytes | Ed25519 wins |
| Signature size | 512 bytes | 64 bytes | Ed25519 wins |
| Sign/verify speed | Slower | Much faster | Ed25519 wins |
| Legacy SSH client support | Universal | OpenSSH 6.5+ (2014) | RSA wins |
| JWT libraries (2026) | RS256 everywhere | EdDSA growing | RSA slight edge |
| TLS 1.3 cert chains | Common | Rare in public CAs | RSA for TLS certs |
| Misconfiguration risk | Weak sizes, bad padding history | Fixed parameters | Ed25519 wins |
| Quantum threat (long-term) | Both need PQC migration | Both need PQC migration | Neither is future-proof alone |
For a deeper curve-family comparison beyond Ed25519 alone, see the related write-up on RSA vs ECC key sizes and trade-offs. Ed25519 is one Edwards-curve option, not the entire ECC landscape.
When should you choose Ed25519 over RSA for SSH keys?
Default to Ed25519 for new SSH keys on servers you control. I use Ed25519 on Ubuntu 22/24 hosts for client projects and sister-site deploy pipelines. The keys are short, operations are fast, and brute-force guessing a 256-bit seed is not a realistic threat model for SSH.
Keep RSA when a human or system on the other side cannot speak Ed25519. Examples include ancient embedded devices, some legacy VPN appliances, and corporate jump boxes stuck on decade-old OpenSSH builds. In those cases, generate RSA 4096—not 2048.
- Use Ed25519 for developer laptops, GitHub/GitLab deploy keys, CI runners, and modern VPS instances.
- Use RSA 4096 when
ssh -Von the remote side is unknown and the business cannot tolerate lockout. - Retire RSA 2048 from production; rotate anything still at that size.
- Never reuse the same key pair across personal and client infrastructure.
Pair key choice with hardening steps from SSH key auth, fail2ban, and port hardening. The algorithm is only one layer. Permissions on ~/.ssh, forced commands, and network restrictions matter just as much.
How do you generate and configure RSA vs Ed25519 keys in production?
Generation takes one command either way. Storage, permissions, and rotation policy matter more than the algorithm name on the tin.
Generate Ed25519 (recommended default)
ssh-keygen -t ed25519 -a 100 -C "deploy@production-2026" -f ~/.ssh/id_ed25519_prod
chmod 600 ~/.ssh/id_ed25519_prod
chmod 644 ~/.ssh/id_ed25519_prod.pub
ssh-copy-id -i ~/.ssh/id_ed25519_prod.pub deploy@203.0.113.10 The -a 100 flag sets bcrypt rounds for the optional passphrase KDF. Use a passphrase on keys that leave your machine. For fully automated CI, store the key in a secret manager and skip the passphrase—but never commit the private file to Git.
Generate RSA 4096 (legacy compatibility)
ssh-keygen -t rsa -b 4096 -a 100 -C "legacy-vendor-access" -f ~/.ssh/id_rsa4096_vendor
chmod 600 ~/.ssh/id_rsa4096_vendor Force algorithm order in sshd_config
On servers you administer, prefer modern algorithms in /etc/ssh/sshd_config:
PubkeyAcceptedAlgorithms ssh-ed25519,ecdsa-sha2-nistp256,rsa-sha2-512,rsa-sha2-256
HostKeyAlgorithms ssh-ed25519,rsa-sha2-512,rsa-sha2-256 Reload SSH after changes: sudo systemctl reload ssh on Ubuntu. Test from a second session before closing your current one. Locking yourself out during a support and maintenance window is an expensive mistake.
authorized_keys hardening example
from="203.0.113.0/24",command="/usr/local/bin/deploy.sh",no-agent-forwarding,no-port-forwarding ssh-ed25519 AAAA... deploy@prod Restrict source IPs and allowed commands per key. On legal-tech portals and client document systems I have shipped, separate deploy keys per environment stopped staging mistakes from touching production.
Which key type performs better for TLS, JWT, and API signing?
SSH is where Ed25519 shines first. Application-layer signing is messier because libraries and standards lag behind server defaults.
JWT and API tokens
Most Laravel and PHP APIs still default to RS256—RSA with SHA-256. It works with virtually every JWT library. EdDSA (Ed25519) appears as EdDSA or Ed25519 in JOSE headers and is supported in common PHP JWT packages when you opt in explicitly.
For greenfield API development, Ed25519 JWTs reduce token size on mobile clients. Before switching, audit every consumer: mobile apps, partner webhooks, and cached API gateways. A token nobody can verify is worse than a bulky RSA signature.
// Laravel config pattern — RS256 (widest compatibility)
'jwt' => [
'algo' => env('JWT_ALGO', 'RS256'),
'keys' => [
'private' => storage_path('app/jwt/private.pem'),
'public' => storage_path('app/jwt/public.pem'),
],
], Generate RSA key material for JWT with OpenSSL when RS256 is required:
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out private.pem
openssl pkey -in private.pem -pubout -out public.pem For Ed25519 JWT keys, OpenSSL 3.x supports:
openssl genpkey -algorithm ED25519 -out ed25519-private.pem
openssl pkey -in ed25519-private.pem -pubout -out ed25519-public.pem Read the related guide on API authentication: JWT vs session vs API keys before picking an algorithm in isolation. Key type is one piece of a broader auth design.
TLS certificates
Public certificate authorities still issue RSA and ECDSA P-256/P-384 chains far more often than pure Ed25519 end-entity certs. Browser trust stores and ACME clients on typical Ubuntu LAMP stacks expect RSA or ECDSA. Use Let's Encrypt ECDSA if you want smaller certs without fighting CA tooling.
Ed25519 belongs in your SSH and internal signing layers first. Public TLS is a separate decision tree.
Cloud secret managers and CI
Long-lived RSA or Ed25519 keys in CI pipelines are a recurring audit finding. Prefer OIDC federation so runners assume short-lived cloud roles. See deploy to AWS from GitHub Actions with OIDC (no keys) and workload identity federation without long-lived keys for patterns that remove static keys entirely.
When keys are unavoidable—legacy vendor SFTP, on-prem GitLab runners—store them in Azure Key Vault or AWS KMS with rotation policies. Never paste private PEM blocks into Slack or ticket comments.
How do you migrate from RSA to Ed25519 without breaking access?
Rotation fails when teams swap keys before confirming every client. Treat migration as a parallel-run exercise, not a Friday-afternoon config edit.
- Inventory every RSA key: developer laptops, CI secrets, cron SFTP jobs, vendor integrations, and backup scripts.
- Generate Ed25519 replacements with new filenames—do not overwrite existing RSA private keys yet.
- Append new public keys to
authorized_keysalongside old RSA entries. - Test login from each client identity: laptop, CI runner, monitoring probe.
- Update application configs that reference key paths (
IdentityFilein SSH config, Deployer recipes, GitLab CI variables). - Remove old RSA public keys only after a full business cycle with zero auth failures.
- Document the rotation date and owner in your runbook.
On Deployer 7 pipelines I maintain for sister legal-tech sites, the deploy user often has two keys during migration. That window typically lasts one to two weeks. Shorter windows risk weekend failures nobody notices until Monday.
SSH config for dual-key period
Host production
HostName 203.0.113.10
User deploy
IdentityFile ~/.ssh/id_ed25519_prod
IdentityFile ~/.ssh/id_rsa4096_legacy
IdentitiesOnly yes IdentitiesOnly yes stops SSH from offering every key in your agent. That prevents "too many authentication failures" lockouts on strict servers.
Common migration failures
Wrong permissions. Private keys must be 600. A world-readable private key makes sshd reject the login with a confusing error.
SELinux or AppArmor contexts. Restored keys from backup tarballs sometimes carry wrong labels. Check audit logs if auth silently fails.
Forced algorithm lists. If PubkeyAcceptedAlgorithms excludes ssh-ed25519, valid keys still fail. Align server and client configs.
Copied comment fields. The trailing comment on a public key is cosmetic. The key material must be one continuous line with no line breaks mid-base64.
For password hygiene during rotation, generate passphrases with the site password generator. Encode or inspect PEM blocks with the Base64 encoder and decoder when debugging corrupted keys.
Document-heavy client portals—such as those built for Mijar Law Associates or Adventure Third Pole Trek—rarely tolerate deploy outages. Parallel keys buy you time to catch edge cases without blocking lawyer uploads or booking payments.
Key Takeaways
- Choose Ed25519 for new SSH and Git deploy keys on any stack running OpenSSH 6.5 or newer.
- Keep RSA 4096 only for legacy clients that reject Ed25519; retire RSA 2048 immediately.
- Use RS256 for JWTs when third-party verifiers are unknown; adopt EdDSA when you control every consumer.
- Run parallel keys during migration, test each client identity, then remove old RSA public keys.
- Prefer OIDC and short-lived tokens in CI over baking long-lived private keys into pipelines.
- Align sshd algorithm lists with your chosen keys and fail closed on permission errors.
People Also Ask
Is Ed25519 more secure than RSA 4096?
Both provide strong classical security margins for typical web and SSH workloads in 2026. Ed25519 avoids weak-size mistakes because the parameters are fixed. RSA security depends heavily on using at least 3072 bits, preferably 4096, with modern padding. Ed25519 also sidesteps historical RSA implementation pitfalls. Neither algorithm addresses post-quantum threats; plan PQC migration separately at the infrastructure level.
Does GitHub support Ed25519 SSH keys?
Yes. GitHub, GitLab, and Bitbucket accept Ed25519 deploy and user keys. Generate with ssh-keygen -t ed25519 and paste the .pub file into your account SSH settings. If a corporate proxy strips unknown key types, fall back to RSA 4096 for that hop only.
Can I use Ed25519 for SSL/TLS website certificates?
Public CAs rarely issue Ed25519 TLS certificates today. Browsers and ACME tooling expect RSA or ECDSA chains. For HTTPS, use ECDSA P-256 from Let's Encrypt if you want smaller certs. Reserve Ed25519 for SSH, internal signing, and application tokens where you control both sides.
What happens if I only have RSA keys on my server?
Clients with Ed25519-only keys cannot authenticate until you add their public keys to authorized_keys. The server does not auto-convert algorithms. Either install the Ed25519 public key alongside existing RSA keys or generate a matching RSA key pair for that client. Check /var/log/auth.log for "Authentication refused: bad ownership or modes" before blaming the algorithm.
Pick the right key for the layer you are securing
RSA vs Ed25519 for keys is not a religious debate. It is a compatibility and operations question. Ed25519 is the better default for SSH and internal signing in 2026. RSA 4096 remains the fallback when something old refuses modern curves. JWT and TLS layers may still need RSA or ECDSA until your entire verifier chain catches up.
Start with an inventory of where keys live today—laptops, cron jobs, CI variables, vendor SFTP. Rotate the highest-risk static keys first. If you want help auditing SSH access, API signing, or deploy pipelines on a production Laravel or WordPress stack, contact us or explore custom software development options. For background on rate-limiting signed API traffic, see Laravel rate limiting with custom keys and read more from about me.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

