Public/private key crypto
Deep dive into asymmetric cryptography: RSA, elliptic curves, hybrid systems, key formats, and the math that makes it work.
The Core Idea
Asymmetric crypto solves a problem that symmetric crypto cannot: how do two people who have never met agree on a secret over a public network? Before 1976, the answer was "you cannot." Whitfield Diffie and Martin Hellman published the key exchange that bears their name and the world changed. RSA followed in 1977 with the first practical public-key system.
The trick is a one-way trapdoor function. Easy to compute in one direction, computationally infeasible to reverse, but trivial if you know a secret (the trapdoor). For RSA the function is modular exponentiation and the trapdoor is the factorization of a large composite number. For elliptic curves the function is scalar multiplication on a curve and the trapdoor is the discrete log.
Two Operations, Two Directions
The single most common mistake even experienced developers make is conflating encryption and signing. They both use a key pair but in opposite directions.
Encryption is about confidentiality. You use the receiver's public key so only they can decrypt. Signing is about authenticity. You use your own private key so anyone with your public key can verify it was you.
In practice, hybrid encryption is standard: generate a one-time symmetric key (AES-256), encrypt the data with it, then encrypt that symmetric key with the receiver's public key. This is what TLS, age, GPG, and Signal all do.
RSA Versus Elliptic Curve
RSA security rests on the difficulty of factoring large semiprimes. To factor a 2048-bit RSA modulus you would need roughly 2^112 operations, which is infeasible. RSA-3072 gives 128-bit security, RSA-4096 gives about 140-bit security. Keys are large because the math requires it.
Elliptic curve cryptography (ECC) gives equivalent security with much smaller keys. A 256-bit ECC key matches a 3072-bit RSA key. The math is harder to explain but the upshot is: smaller signatures, faster operations, less bandwidth.
Modern choices.
- Ed25519: signature scheme on Curve25519 by Daniel Bernstein. Fast, constant-time, no parameter choices to get wrong. SSH, age, Signal, modern OpenSSH all default to this.
- ECDSA P-256 (also called secp256r1): NIST curve, used in TLS, JWT (ES256), VAPID. Not as elegant as Ed25519 but ubiquitous.
- RSA-2048: still common in TLS certificates and JWT (RS256). Slow signing, fast verifying. Avoid for new systems unless you must interop.
A rough perf comparison on modern hardware.
- RSA-2048 sign: ~1ms, verify ~30 microseconds
- ECDSA P-256 sign: ~50 microseconds, verify ~150 microseconds
- Ed25519 sign: ~30 microseconds, verify ~80 microseconds
ECDSA verifies are slower than RSA verifies but ECDSA signing is way faster. For high-throughput verify workloads (a server checking many client signatures), RSA can be the right call.
Key Formats You Will Encounter
Keys live in a zoo of file formats. The big ones.
- PEM: base64-wrapped DER, with header lines like
-----BEGIN PRIVATE KEY-----. Most common in the Unix world. - DER: raw binary ASN.1. Used in TLS internals.
- PKCS#8: standard wrapper for private keys, encrypted or not. Modern default.
- PKCS#1: old RSA-specific format, header says
-----BEGIN RSA PRIVATE KEY-----. - OpenSSH: SSH-specific format, used by
ssh-keygen. Header-----BEGIN OPENSSH PRIVATE KEY-----. - JWK: JSON Web Key, used by JWT and VAPID. Public keys go in URLs and HTTP headers as base64url.
When something does not work, 80% of the time it is a format mismatch. The library wants PKCS#8 and you fed it PKCS#1. Convert with openssl pkcs8 -topk8 -nocrypt -in old.pem -out new.pem.
The Hybrid Cryptosystem
Asymmetric crypto is slow. AES-256-GCM on modern hardware with AES-NI runs at 10+ GB/s. RSA tops out at maybe 1000 ops/sec. So no real protocol encrypts bulk data with asymmetric crypto.
The pattern is universal.
TLS does this for every connection. The handshake does an asymmetric key agreement (ECDHE, usually), then the rest of the session uses AES-GCM or ChaCha20-Poly1305.
Forward Secrecy
A subtlety: if a server uses RSA key exchange and someone records the traffic, then later steals the server's private key, they can decrypt all the old recordings. Bad.
The fix is ephemeral Diffie-Hellman (DHE or ECDHE). Each session generates a fresh key pair, agrees on a session key, then throws the ephemeral keys away. The long-term server key is only used to sign the ephemeral public key, not to derive the session key. Even if the server's private key leaks tomorrow, yesterday's traffic stays safe.
TLS 1.3 makes forward secrecy mandatory. If you are configuring a TLS server in 2026 and it is not ECDHE, fix it.
Common Pitfalls
- Reusing nonces in ECDSA. ECDSA requires a random nonce k per signature, and reusing k across two signatures leaks the private key. This is how the PlayStation 3 was broken by fail0verflow. Use Ed25519 if you can, since it derives the nonce deterministically and avoids this footgun.
- Confusing key fingerprints with public keys. The fingerprint is a hash of the public key, useful for visual comparison, not the key itself. Do not try to verify signatures against a fingerprint.
- Trusting unverified public keys. The whole point is undermined if you fetch the "server's public key" over plaintext HTTP. You need an out-of-band trust root (a CA, TOFU, or a manually pinned key).
- Storing private keys in source control. Even private repos. Use a KMS or a secrets manager.
Interview Soundbites
- "Asymmetric is slow, so we use it once to bootstrap a symmetric session key. That is the hybrid pattern, used by every real protocol."
- "Forward secrecy means a stolen private key cannot decrypt past traffic. TLS 1.3 requires it via ECDHE."
- "Ed25519 over ECDSA when you have the choice. No nonce footgun, faster, smaller."
- "Public keys are not secret. The whole point is that you can publish them."
Learn more
- Docs
- Docs
- ArticleCloudflare: ECDSA primerCloudflare
- DocsSerious Cryptography by Jean-Philippe AumassonNo Starch Press