When you request a certificate you pick a key algorithm, and most people take whatever the tutorial used. For new deployments that default should be ECDSA on the P-256 curve. It produces smaller keys and signatures than RSA and signs faster, which is the work a server actually does on every handshake. RSA still has one job worth keeping it around for: talking to clients too old to understand elliptic curves. This post measures the difference with openssl so you can see exactly what you trade.

The Short Version

Default to ECDSA P-256 for anything new. The keys are a fraction of the size, the signatures are smaller, and a busy server signs handshakes far faster than it can with RSA. Reach for RSA only when you have to serve clients that predate ECDSA support, and when you do, serve both certificates so no one gets downgraded. The numbers below back all of that up.

Generating a Key of Each Type

RSA takes a bit length. ECDSA takes a named curve. These four commands produce the keys compared throughout this post:

# RSA at two common strengths
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out rsa2048.key
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out rsa4096.key

# ECDSA P-256, two equivalent spellings (older ecparam form and the newer genpkey form)
openssl ecparam -name prime256v1 -genkey -out ecdsa-p256.key
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out ecdsa-p256.key

# ECDSA P-384, for when you need a larger curve
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-384 -out ecdsa-p384.key

Wrap a key in a self-signed cert and openssl x509 -noout -text tells you what you built. The Public Key Algorithm and key-size lines are the ones that matter:

$ openssl x509 -in rsa2048.crt -noout -text | grep -A1 "Public Key Algorithm"
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)

$ openssl x509 -in ecdsa-p256.crt -noout -text | grep -A1 "Public Key Algorithm"
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)

Size: Where ECDSA Wins Outright

A 256-bit ECDSA key carries security comparable to a 3072-bit RSA key, so it holds equivalent strength in far fewer bits. That gap is not theoretical. Generate one of each, measure the public key, the signature, and the finished certificate, and the bytes are concrete:

Algorithm Public key (DER) Signature Certificate (PEM)
RSA-2048 294 B 256 B 1,119 B
RSA-4096 550 B 512 B 1,814 B
ECDSA P-256 91 B ~71 B 583 B
ECDSA P-384 120 B ~103 B 668 B

The signature column is measured from openssl dgst -sha256 -sign. RSA signatures are fixed at the key's modulus size. ECDSA signatures are DER-encoded and wobble a byte or two per signature, so P-256 lands at 70 to 72 bytes and P-384 at 102 to 104. Either way an ECDSA P-256 certificate is roughly half the size of an RSA-2048 one and under a third of an RSA-4096. Every one of those bytes crosses the wire on every new connection.

Speed: A Split Decision

Here is where the honest answer gets more interesting than "ECDSA is faster." It depends on which operation you mean. Run the benchmark yourself:

$ openssl speed rsa2048
...
                               keygen     signs    verify keygens/s    sign/s  verify/s
                    rsa2048 0.053736s 0.000342s 0.000020s      18.6    2921.8   50366.0

$ openssl speed ecdsap256
                              sign    verify    sign/s verify/s
 256 bits ecdsa (nistp256)   0.0000s   0.0001s  42760.0  14174.1

On OpenSSL 3.x the RSA run also prints a keygen and encapsulation table, trimmed here to the signature line. ECDSA P-256 signs at 42,760 operations a second against RSA-2048's 2,922, about fifteen times faster on this machine. RSA turns the tables on verification: 50,366 a second versus ECDSA's 14,174, roughly three and a half times faster.

Which one wins depends on who is doing the work. In a TLS handshake the server signs and the client verifies. A server terminating thousands of connections a second spends its CPU on the signing side, and that is exactly where ECDSA is far ahead. The client eats the slower verification, once, on a device that is idle the rest of the time. For a high-traffic site or an API gateway the server-side signing throughput is the number that sets your capacity, and ECDSA wins it decisively. Do not repeat the common shorthand that "ECDSA is just faster." RSA verification is faster, and if you ever claim otherwise the benchmark above will contradict you.

The Compatibility Catch

ECDSA's weakness is reach. Almost everything current supports it, but very old clients, ancient Android builds, some legacy payment hardware, and a few embedded stacks only speak RSA. Point an ECDSA-only certificate at that audience and those clients cannot complete the handshake. This is the entire reason RSA is still worth keeping in a modern setup.

Serving Both Certificates

You do not have to pick one algorithm for everyone. nginx accepts more than one ssl_certificate directive, so you can load an ECDSA certificate and an RSA certificate on the same server and let it choose per connection:

server {
    listen 443 ssl;
    server_name example.com;

    # ECDSA: modern clients that advertise ecdsa_* signature algorithms get this
    ssl_certificate     /etc/ssl/example.com/ecdsa.crt;
    ssl_certificate_key /etc/ssl/example.com/ecdsa.key;

    # RSA: fallback for clients that only understand RSA
    ssl_certificate     /etc/ssl/example.com/rsa.crt;
    ssl_certificate_key /etc/ssl/example.com/rsa.key;

    ssl_protocols TLSv1.2 TLSv1.3;
}

During the handshake nginx reads the client's advertised signature algorithms and hands back the matching certificate: ECDSA to anything modern, RSA to the long tail. You get ECDSA's smaller, faster handshake for the bulk of traffic and RSA compatibility for the clients that need it. openssl s_client confirms which one a modern client actually negotiated:

$ openssl s_client -connect example.com:443 -tls1_3
...
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 256 bit
Peer signature type: ecdsa_secp256r1_sha256

A 256-bit server public key and an ecdsa_secp256r1_sha256 peer signature mean the ECDSA certificate was served. Point an old client at the same server and it would fall back to the RSA one. The cost of this arrangement is real: two certificates to renew, two keys to protect, and twice the surface for something to expire unnoticed.

Monitor for Algorithm Drift

A deliberate algorithm choice only holds if you can see what is actually deployed. Across dozens of endpoints, key algorithm drifts the way expiry does: quietly, one host at a time, until an audit turns up an RSA-1024 certificate on an internal service nobody remembers issuing. Check any single live endpoint by hand with the SSL check at mrdns.com, and harden the server once you have chosen with the nginx TLS guide at goodtls.com.

Watching an entire fleet by hand does not scale. Generator Labs certificate monitoring reports the key algorithm and size alongside expiry for every endpoint you track, so a weak or off-standard key surfaces before an auditor finds it. The same size pressure is why post-quantum signatures are such a hard migration, since they dwarf even RSA, as we covered in post-quantum TLS. Pick ECDSA on purpose, keep RSA where you genuinely need it, and get started watching that the choice stuck.

Back to Blog