Industry

ECDSA or RSA: picking a key algorithm you won't regret at renewal time

July 3, 20268 min readCertPulse Engineering

the one metric where RSA still wins

boring consensus first, because it's mostly right: for basically everything that matters during a handshake, P-256 ECDSA beats RSA-2048.

a P-256 public key is 32 bytes. an RSA-2048 public key is 256 bytes, and the cert hauling it around gets chunkier still once you add the signature. that gap shows up on the wire every handshake, and it shows up worst on your server's CPU. here's the part people forget: RSA and ECDSA load different ends of the connection. RSA signing — the private-key op your server runs on every handshake — is expensive. RSA verification, the client's job, is cheap. ECDSA flips half of that. signing is cheap, verifying is a bit more work for the client. and since your server is the one doing thousands of handshakes a second while each client does one, shoving the expensive op off your box is the entire point. numbers move around by library and hardware, but P-256 signing running several times faster than RSA-2048 is a normal afternoon, and the gap turns into a bloodbath against RSA-3072 or 4096.

so: key size, server-side handshake cost, bandwidth — ECDSA takes all three. the one thing it doesn't win is reach. the raw count of clients on earth that can finish the handshake. and reach is the metric that eats your weekend, because it fails closed and it fails quiet.

the compatibility long tail nobody actually measures

this is the ugly part of the whole ECDSA-vs-RSA argument. the clients that can't do ECDSA don't hand you a polite error. they just don't connect, and whether you ever find out depends entirely on whether the human behind that client can reach a human who can reach you.

the tail is real, and it's older than you'd think. java is the classic offender. anything on a pre-8 JRE, plus a pile of enterprise middleware pinned to some fossilized TLS library, will negotiate RSA all day and gag on an ECDSA-only server. payment terminals and POS gear run on certification cycles measured in years — "it passed PCI in 2016" is not a sentence that ends with prompt cipher updates. embedded stuff ships a frozen stack constantly: industrial controllers, medical gear, the swarm of IoT things somebody deployed two months before the vendor went bankrupt. and old android is the volume play. anything before roughly 4.x had patchy ECDSA support in the system stack. tiny slice of consumers now. potentially a huge slice of one specific market.

the real mistake is deciding this in the abstract. you don't serve "the internet." you serve your clients, and their shape is knowable before you touch anything.

three places to look. one: your own access logs. if you're logging negotiated cipher suite and TLS version — and you should be — you already have a record of what your clients actually speak. pull the version distribution and the tail's shape jumps right out. two: fingerprinting. JA3 and its successor JA4 hash the client hello's cipher list and extensions, and a fingerprint distribution tells you not just what clients negotiated but what they offered, which is the thing you need to predict an ECDSA switch. three, the one everybody skips: watch what your CA is already handing you across the estate. certificate transparency logs are a public record of every cert issued for your domains, and they'll show you exactly where RSA is dug in.

rule of thumb. if you serve the public web to consumers on normal browsers, your tail rounds to nothing and you should quit worrying. if you serve businesses, embedded fleets, or anything with money moving through it, measure before you guess. the cost of guessing wrong is a whole class of user who can't reach you and can't tell you why.

dual-cert serving: stop choosing

this was always a fake binary, and decent serving software has known it for years. during the handshake the client advertises which signature algorithms it supports. a server holding both an ECDSA and an RSA cert for the same hostname just picks per connection — ECDSA for the modern crowd, RSA for the tail. everybody gets the best cert they can actually use.

where it's clean: nginx has taken multiple certificate directives on one server block forever. point it at an ECDSA chain and an RSA chain, it reads the client hello, done. no app changes, no separate vhosts. HAProxy does the same — load several certs on a frontend, it matches the negotiated algorithm. on both it's mature and boring, which is precisely what you want out of the layer terminating your TLS.

where it gets murky is the managed load balancers, and this is where people get bitten. AWS ACM will cheerfully issue you both an RSA and an ECDSA cert, but whether your LB serves both at once depends on the LB and how you bolted them on. ALBs let you attach multiple certs to a listener over SNI and will do the selection, but the behavior is chained to the listener's security policy — and a policy without ECDSA suites quietly guts what "dual" even means. azure key vault stores whatever you throw in it; the selection logic lives in whatever terminates TLS (application gateway, front door), each with its own opinions about multi-cert listeners. GCP certificate manager and its LBs handle both, but again, the selection rides on how the cert map and SSL policy are set.

the failure mode to fear is the silent one. you think you're serving dual. the ECDSA path looks great in testing because every test client you own is modern. and the RSA fallback was never actually wired up, because the security policy excluded it or the second cert never attached. your modern clients are fine. your tail is quietly dying, and your tail does not file tickets. so test the fallback on purpose: force an RSA-only client hello and confirm you get the RSA cert back. can't produce an old client easily? a command-line TLS client clamped to RSA signature algorithms will do the job.

why 47-day lifetimes sharpen this

this used to be set-it-and-forget-it. not anymore. the CA/browser forum's ballot SC-081v3 is marching cert lifetimes down from 398 days toward 47 by march 2029. the 200-day phase is live as of march 2026, 100 days lands march 2027, 47 days (with a 10-day reuse window for domain validation) in 2029.

shorter lifetimes multiply every per-renewal cost you've got. a cert that renewed once a year now renews something like eight times a year. and if you generate a fresh keypair on every renewal — a perfectly defensible posture — you now pay the keygen and rotation tax eight times as often.

that tax isn't symmetric. RSA keygen is genuinely slow: you're hunting for large primes, and RSA-4096 generation can eat a real fraction of a second, or worse, on weak hardware. ECDSA keygen is trivial next to it — a P-256 keypair is basically instant. once a year, nobody noticed. every few weeks, across hundreds or thousands of certs, some of it on tiny instances or inside HSMs with throttled throughput? now it stops being academic. smaller keys, cheaper generation, fewer bytes shipped every time you push the new cert to every endpoint that needs it.

none of this makes RSA unusable at 47 days. it just makes ECDSA's operational edge compound, because you're paying it on repeat now. if you were on the fence for something high-volume, the renewal frequency alone should tip you.

a decision framework by workload

public consumer web. go ECDSA. the browsers that can't do it round to zero, and you get faster handshakes plus cheaper rotation. still nervous? serve dual — the marginal cost of also carrying an RSA cert is tiny and it kills the risk outright.

internal mTLS between services. you own both ends, which makes this the easy one — you know exactly what your clients speak because you wrote them. go ECDSA, skip the RSA cert, pocket the cheap keygen when your mesh rotates on a tight schedule.

IoT and embedded. measure first, and assume the worst. this is where the frozen stacks live. any doubt about the fleet's crypto, serve dual so modern devices get ECDSA and the legacy ones drop to RSA. do not go ECDSA-only until you've got hard proof every device can handle it.

API endpoints. entirely about who calls you. modern SDKs and cloud services? ECDSA, no hesitation. enterprise integrations running who-knows-what java on-prem? check your access logs for the negotiated signature algorithms before you commit, and default to dual if the client population is a black box.

the thread through all four: you can't make this call well without knowing what's actually deployed. which certs use which algorithm, which endpoints present dual versus single, and where an "ECDSA migration" quietly left an RSA cert doing all the real work. that's a visibility problem before it's an algorithm problem, and keeping a live inventory of what's actually in play across AWS, azure, GCP, and your external endpoints is exactly what certpulse is built to surface — so the switch you think you made is one you can confirm.

pick ECDSA where you can, keep RSA where you must, serve both when you're not sure. the algorithms aren't rivals. the only real mistake is choosing blind.

-- alex

measure the tail before it measures you.

This is why we built CertPulse

CertPulse connects to your AWS, Azure, and GCP accounts, enumerates every certificate, monitors your external endpoints, and watches Certificate Transparency logs. One dashboard for every cert. Alerts when auto-renewal fails. Alerts when certs approach expiry. Alerts when someone issues a cert for your domain that you didn't request.

If you're looking for complete certificate visibility without maintaining scripts, we can get you there in about 5 minutes.

ECDSA or RSA: picking a key algorithm you won't regret at renewal time | CertPulse