ecdsa.com
← All articles

ECDSA vs RSA: which signature algorithm and when

Both algorithms do the same job — prove that a message was signed by the holder of a private key. They get there with very different math, and that difference shows up in key sizes, performance profiles, operational requirements and, soon, retirement dates.

Two algorithms, one job

RSA signatures are built on modular exponentiation with a large composite modulus: the private key is derived from two secret primes, and the difficulty of factoring their product is what keeps the key private. ECDSA (the Elliptic Curve Digital Signature Algorithm, standardized in FIPS 186-5) instead works in the group of points on an elliptic curve, where the hard problem is the elliptic-curve discrete logarithm.

The practical consequence of the different hard problems: attacks on factoring scale better than attacks on elliptic-curve discrete logs, so RSA keys have to grow much faster than EC keys to keep the same security margin. That single fact drives most of the size and performance differences below.

Size: keys and signatures at equal strength

NIST's comparison of security strengths (see SP 800-57 Part 1) puts a 256-bit elliptic-curve key in the same 128-bit security class as a 3072-bit RSA modulus:

Security levelECDSA curveEC public keyEC signatureRSA modulusRSA signature
112-bitP-22457 B / 29 B*56 B raw2048-bit256 B
128-bitP-25665 B / 33 B*64 B raw (~70–72 B DER)3072-bit384 B
192-bitP-38497 B / 49 B*96 B raw7680-bit960 B
256-bitP-521133 B / 67 B*132 B raw15360-bit1920 B

(*uncompressed / compressed point encoding.) At the 128-bit level — the floor for new systems today — an ECDSA P-256 signature is 64 bytes against RSA-3072's 384 bytes, and the public key is roughly a tenth of the size. Even the widely deployed (and lower-margin) RSA-2048 produces 256-byte signatures. Where every byte counts — certificates in a TLS handshake, tokens in an HTTP header, transactions on a blockchain — elliptic curves win on size, every time.

Note the two ECDSA signature numbers: 64 bytes "raw" versus ~70–72 bytes DER-encoded. The same mathematical signature has two common wire encodings, and mixing them up is one of the most frequent causes of "invalid signature" errors. That topic gets its own article.

Speed: the signing/verification asymmetry

The two algorithms have opposite performance profiles, and the asymmetry is worth internalizing because it decides real architectures:

  • RSA verification is very fast. Verifying means one modular exponentiation with the public exponent, which is almost always the small value 65537. This is why RSA held on so long in certificate chains: a certificate is signed once and verified billions of times.
  • RSA signing is slow, because it exponentiates with the full-size private exponent over a 2048–4096-bit modulus. RSA key generation is slower still — it has to search for large random primes, which can take noticeable fractions of a second and varies unpredictably.
  • ECDSA signing is fast — one scalar multiplication over a 256-bit field, typically several times to an order of magnitude faster than an RSA-2048 signature, with a much bigger gap against RSA-3072. EC key generation is essentially free (one scalar multiplication), which matters for ephemeral and per-device keys.
  • ECDSA verification is slower than RSA verification (roughly two scalar multiplications), though still fast in absolute terms on modern hardware.

You can see the size difference directly in a few lines of Node.js:

node — compare signature sizes
import { generateKeyPairSync, sign } from "node:crypto";

const message = Buffer.from("measure me");

const ec = generateKeyPairSync("ec", { namedCurve: "P-256" });
const rsa = generateKeyPairSync("rsa", { modulusLength: 3072 }); // slow: prime search

const ecSig = sign("sha256", message, ec.privateKey);  // DER-encoded by default
const rsaSig = sign("sha256", message, rsa.privateKey);

console.log("ECDSA P-256:", ecSig.length, "bytes"); // ~70-72 (64 raw)
console.log("RSA-3072:  ", rsaSig.length, "bytes"); // 384

Where each one lives today

  • TLS / X.509. Both are everywhere. RSA still dominates the installed base of certificates, but ECDSA certificates (P-256, P-384) are standard issue from major CAs and shrink handshakes meaningfully; many large sites serve ECDSA with an RSA fallback. TLS 1.3 supports both signature families natively.
  • SSH. The ecosystem has moved to elliptic curves: Ed25519 (a related EC signature scheme, not ECDSA) is the usual default for new keys, with ECDSA P-256 also common. RSA keys still work, but the legacy ssh-rsa signature scheme (SHA-1-based) has been disabled by default in recent OpenSSH releases — RSA keys must use the SHA-2 variants.
  • JWTs. RS256 (RSA) is the historical default of the identity ecosystem; ES256 (ECDSA P-256) is the compact modern choice and is mandated by several platforms (Apple's token APIs, DPoP, most WebAuthn/passkey credentials). The trade-offs are specific enough that we wrote a dedicated guide: ES256 vs RS256 for JWTs. You can inspect real tokens with the JWT debugger.
  • Blockchains. Effectively ECDSA-only territory: Bitcoin and Ethereum both sign with ECDSA over the secp256k1 curve (Bitcoin has additionally adopted Schnorr signatures with Taproot). RSA's signature sizes make it a non-starter where every transaction byte is paid for.
  • Code signing and firmware. Historically RSA-heavy, increasingly mixed; constrained devices favor ECDSA for the small keys and fast, low-memory signing.

ECDSA's catch: the nonce must be perfect

ECDSA has one operational requirement RSA simply does not have: every signature consumes a fresh secret number k (the nonce), and the scheme's security depends on that number being unique and uniformly random for every single signature. The failure modes are unforgiving:

  • If the same k is ever used for two different messages under one key, the private key can be computed from the two signatures with elementary algebra. This is exactly what happened in the famous 2010 PlayStation 3 incident, where a constant nonce exposed the console's signing key.
  • Even a partially predictable or slightly biased nonce, observed across many signatures, can be enough to reconstruct the key using lattice techniques. A weak system random number generator at signing time is therefore a key-compromise risk, not just a quality issue.

The standard answer is deterministic ECDSA, specified in RFC 6979: derive k from the private key and the message digest via HMAC, so the same input always produces the same, well-distributed nonce and no signing-time randomness is required. FIPS 186-5 now permits deterministic ECDSA, and most modern libraries implement RFC 6979 or a hedged variant (deterministic derivation mixed with extra entropy). When choosing a library, this is one of the first things to check. RSA, by contrast, needs no per-signature randomness for PKCS#1 v1.5, and the random salt in RSA-PSS is not key-compromising if it repeats.

The post-quantum clock is running for both

Whatever you pick, plan for its retirement. A sufficiently large quantum computer running Shor's algorithm breaks factoring and elliptic-curve discrete logs alike — RSA and ECDSA fall together. NIST has already published the transition schedule in NIST IR 8547 (initial public draft): ECDSA and RSA are deprecated after 2030 and disallowed after 2035 for federal use — a timeline the wider industry is expected to track.

The named successors are ML-DSA (lattice-based, standardized in FIPS 204) and SLH-DSA (hash-based, FIPS 205), with the Falcon-derived FN-DSA to follow. Be ready for a size shock: an ML-DSA-65 signature is around 3.3 KB — fifty times a P-256 signature — which is why protocol work on hybrid and composite certificates is still ongoing. The practical takeaway for today is not "adopt PQC everywhere now" but build crypto-agility: know every place your systems sign, keep algorithm choices configurable, and avoid hard-coding key or signature sizes.

So which one should you use today?

Want to see the differences with real bytes? Generate or paste a signature into the ECDSA signature verifier — it auto-detects the curve and encoding and shows exactly what it verified.