Back to Blog
Security

RSA, Elliptic Curves, Lattices?

A worked comparison of the three families that secure the internet. It covers the hard problems underneath, why key sizes differ by orders of magnitude, how derivation really works, and what a quantum computer does to each.

Suraj Kumar
November 11, 2025
36 min read

Three ways to hide a secret in plain sight

Every public key system rests on the same trick: find an operation that is cheap to run forwards and, as far as anyone knows, ruinously expensive to run backwards. The three families that matter differ only in which operation.

FamilyForward (easy)Backward (hard)
RSAMultiply two primesFactor the product
Elliptic curveAdd a point to itself k timesRecover k from the result
LatticeAdd small noise to a linear systemSolve the system despite the noise

That table looks like three arbitrary choices. It is not. Each row has a different shape of hardness. The shape, rather than the cleverness of the construction, is what determines key sizes, derivation cost, and survival against a quantum computer. This post works through all three.

Part I. RSA, multiplication you cannot undo

The construction

Pick primes p and q, set n = p*q, and publish n with a small exponent e (almost always 65537). Compute the private exponent from the group order:

λ(n)=lcm⁡(p−1,  q−1)Carmichael functiond≡e−1(modλ(n))extended Euclid\begin{aligned} \lambda(n) &= \lcm(p-1,\; q-1) && \text{Carmichael function}\\ d &\equiv e^{-1} \pmod{\lambda(n)} && \text{extended Euclid} \end{aligned}

Signing is s=md mod ns = m^{d} \bmod n, and verification is m=se mod nm = s^{e} \bmod n. Correctness comes from Carmichael's theorem, not Euler's, since we reduced modulo λ(n)\lambda(n) rather than φ(n)\varphi(n): we get med≡m(modn)m^{ed} \equiv m \pmod{n} because ed≡1(modλ(n))ed \equiv 1 \pmod{\lambda(n)}. (Using λ\lambda gives a smaller dd than the textbook φ\varphi formulation, and because n=p⋅qn = p\cdot q is squarefree the congruence holds for every mm rather than only those coprime to nn.)

Why the keys are enormous

Factoring is not exponential. The general number field sieve runs in Ln[13, 64/93 ]L_n\bigl[\tfrac{1}{3},\, \sqrt[3]{64/9}\,\bigr], where the L notation interpolates between polynomial and exponential growth:

Ln[α, c]  =  exp⁡ ⁣((c+o(1)) (ln⁡n)α (ln⁡ln⁡n)1−α)L_n[\alpha,\, c] \;=\; \exp\!\Bigl( \bigl(c + o(1)\bigr)\,(\ln n)^{\alpha}\,(\ln\ln n)^{1-\alpha} \Bigr)

The two endpoints are the point of the notation: α=0\alpha = 0 gives something polynomial in ln⁡n\ln n, and α=1\alpha = 1 gives something exponential in it. Factoring sits strictly between them. Substituting α=1/3\alpha = 1/3 and c=64/93≈1.923c = \sqrt[3]{64/9} \approx 1.923:

Ln ⁣[13,  64/93 ]  =  exp⁡ ⁣((1.923…+o(1)) (ln⁡n)1/3 (ln⁡ln⁡n)2/3)L_n\!\left[\tfrac{1}{3},\; \sqrt[3]{64/9}\,\right] \;=\; \exp\!\Bigl( \bigl(1.923\ldots + o(1)\bigr)\,(\ln n)^{1/3}\,(\ln\ln n)^{2/3} \Bigr)

The o(1) is not decoration. It absorbs a real gap. Evaluate the leading term alone and you get 117 bits of work for RSA-2048 where NIST credits 112, and 139 for RSA-3072 where NIST credits 128. The expression gives the growth rate, not a work factor you should quote at a customer.

That cube root in the exponent is the whole story. Because the work grows subexponentially in the bit length, you have to grow the modulus very fast to buy linearly more security:

25610242048307240962^02^642^1282^1922^256work factor (log2 operations)128 bit security floorECDLP - Pollard rho ~ 2^(n/2)RSA - GNFS, subexponentialShor - polynomial (both)256 bit curveRSA-3072key size (bits)The gap between the two solid curves is the entire reason ECC replaced RSA in new protocols.The dashed curve is the reason neither survives a cryptographically relevant quantum computer.
Attack work factor against key size for GNFS, Pollard rho, and Shor

Read the two solid curves. Pollard's rho against an elliptic curve is a straight line of slope 1/2, so a 256 bit curve costs 2^128 operations. GNFS against RSA crawls. You need a 3072 bit modulus for the same 2^128. Push to 256 bit security and RSA needs 15360 bits, a 1920 byte key.

11212819225616 B64 B256 B1024 B4096 Bpublic key size (bytes, log scale)ML-KEM-768 ek - 1184 BML-DSA-65 pk - 1952 Bthe widening gapRSA-2048RSA-3072RSA-7680RSA-15360P-224Curve25519P-384P-521classical security level (bits)Doubling ECC security doubles the key. Doubling RSA security multiplies the modulus by five, and the ratio keeps growing.At 256 bit security an RSA key is about 29x an elliptic curve key - and a quantum computer breaks both.
Public key size against security level, log scale

Doubling elliptic curve security doubles the key. Doubling RSA security multiplies the modulus by about five (3072 to 15360 bits), and the ratio keeps growing toward the asymptotic eight. Two curves, diverging without bound. That divergence is the entire reason new protocols stopped choosing RSA.

Key generation is a search, and that matters

Everything else in this post generates keys by deriving them. RSA has to go looking:

code
repeat:  sample a random odd 1536-bit integer
         run Miller-Rabin
until:   probably prime

By the prime number theorem, near 2^1536 roughly one odd number in ln(2^1536)/2 ~ 532 is prime, so expect about 532 candidates per prime, and two primes per key. Hundreds of milliseconds, with a tail you cannot bound. On an embedded device it can be seconds.

This has a real consequence: RSA key generation is the one primitive here that can fail to finish on time, which is why smartcards take seconds to generate an RSA key (some are provisioned with one at the factory) and why nobody generates RSA keys per session.

Part II. Elliptic curves, geometry as a group

The group law is literally drawing a line

An elliptic curve over a field is the solution set of y^2 = x^3 + ax + b (with 4a^3 + 27b^2 != 0, which rules out cusps and self intersections). Its points form an abelian group under an operation you can draw:

E : y^2 = x^3 - 3x + 5over R, nonsingular, since 4a^3 + 27b^2 = 567 != 0Addition- chord through two points-202-4-2024reflectPQRP+Qlambda = (y2-y1)/(x2-x1) = 0.2520(2.0635, -2.7561) - verified on EDoubling- tangent at one point-202-4-2024reflectQR2Qlambda = (3x1^2+a)/2y1 = -0.6708(0.4500, -1.9342) - verified on Ecurve Echord / tangentthird intersection RresultO (infinity) is the identity; -P is P mirrored in the x axis.
The chord and tangent group law on an elliptic curve

Draw the chord through P and Q. A cubic meets a line in exactly three points, so there is a third intersection R. Reflect it across the x axis and you have P + Q. Algebraically:

λ=y2−y1x2−x1(chord)orλ=3x12+a2y1(tangent)x3=λ2−x1−x2y3=λ (x1−x3)−y1\begin{aligned} \lambda &= \frac{y_2 - y_1}{x_2 - x_1}\quad\text{(chord)} \qquad\text{or}\qquad \lambda = \frac{3x_1^{2} + a}{2y_1}\quad\text{(tangent)}\\[2pt] x_3 &= \lambda^{2} - x_1 - x_2\\ y_3 &= \lambda\,(x_1 - x_3) - y_1 \end{aligned}

The figure above is computed from those formulas rather than drawn by hand. The plotted P + Q satisfies the curve equation to floating point precision.

From geometry to hardness

Real curves are pretty. Cryptography uses curves over a finite field F_p, where the algebra is identical but the picture is not.

E(F_127) : y^2 = x^3 - 3x + 5 (mod 127)126 affine points + infinity, group order 127, which is prime - so every point is a generator12345678x (mod 127)y (mod 127)Successive multiples of G11G = (5, 49)22G = (9, 31)33G = (38, 36)44G = (55, 90)55G = (98, 50)66G = (112, 55)77G = (52, 54)88G = (7, 94)Why this is the whole gameComputing 8G takes three doublings,2G, 4G, 8G - microseconds.Recovering k = 8 from the markedpoint requires searching the order.Same equation, same group law. Over a finite field the shape disappears - and with it, any way to guess k.
The same curve over the finite field of 127 elements, with multiples of a generator marked

That is the same equation. Every one of those 126 points satisfies y^2 = x^3 - 3x + 5 (mod 127), and the group order is 127 - prime, so every point generates the whole group. The numbered dots are 1G through 8G, computed with exactly the chord and tangent rules from the previous figure.

Look at where they land: (5,49), (9,31), (38,36), (55,90), (98,50)... no drift, no direction, nothing to extrapolate from. The smoothness that makes the group law easy to draw evaporates over a finite field, and with it every geometric shortcut an attacker might hope for. The forward direction is still three doublings, 2G, 4G, 8G. The reverse is a search. Scalar multiplication Q = k*G is repeated addition, done in O(log k) steps by double and add. Recovering k from Q is the elliptic curve discrete logarithm problem. The best known classical attack, Pollard's rho, is a birthday collision needing about sqrt(pi*N/4) group operations, where N is the order of the base point. For an n-bit curve N ~ 2^n, so that is sqrt(pi/4) * 2^(n/2) ~ 2^(n/2). The constant 0.886 costs the attacker about a sixth of a bit and is conventionally dropped.

Exponential, with no subexponential shortcut known. That is why a 256 bit curve matches a 3072 bit RSA modulus.

Curve25519's derivation, and why it never fails

code
seed  <- 32 random bytes
h     = SHA-512(seed)
a     = clamp(h[0..32])       // clear low 3 bits, set bit 254, clear bit 255
A     = a * G                 // one scalar multiplication

The clamping is the interesting part. Curve25519 has cofactor 8, so the group contains a small order 8 subgroup alongside the prime order one. Clearing the low three bits makes the scalar a multiple of 8, which in X25519 key exchange annihilates any small order component a hostile peer might inject. The attack is neutralised arithmetically rather than by validating the input point. Setting bit 254 fixes the leading bit so a Montgomery ladder runs the same number of iterations for every key, which is what makes it constant time.

The payoff is that every 32 byte string is a valid seed. Nothing can be rejected, and nothing can loop.

RSA-30721Sample random odd 1536 bit p2Miller-Rabin, ~532 tries3Repeat for q4n = p*q, L = lcm(p-1, q-1)5d = e^-1 mod L (e = 65537)hundreds of ms - unbounded tailKey generation is a search. You cannotbound how long it takes.Ed255191Sample 32 random bytes (seed)2h = SHA-512(seed)3Clamp h[0..32] -> scalar a4A = a*G (one scalar mult)5Public key = compress(A)~6 us - constant timeEvery 32 byte string is a valid seed.Nothing can fail.ML-KEM-7681Sample 32 byte seed d2(rho, sigma) = SHA3-512(d)3A = XOF(rho) - expand matrix4s, e <- CBD(PRF(sigma)) - noise5ek = (A*s + e, rho)~30 us - deterministicThe public matrix is regenerated fromrho, never transmitted.Post quantum key generation is closer to elliptic curves than to RSA: expand a seed, sample, done.
Key generation compared across the three families

Part III. Lattices, hardness from geometry in high dimensions

What a lattice is

Given linearly independent basis vectors b_1 ... b_n, the lattice is every integer combination:

code
L = { sum z_i*b_i  :  z_i in Z }

A discrete grid of points, infinite in extent. Two problems on it are believed hard in high dimension. SVP asks for the shortest nonzero vector, and CVP asks for the lattice point nearest to an arbitrary target.

The trapdoor is which basis you hold

Here is the insight the whole field rests on, and it is genuinely beautiful: a lattice has infinitely many bases, and they are not equally useful.

One lattice, two bases, the same rounding algorithmb' = M*b with M = [[1,3],[1,4]], det M = 1, so an identical point set, opposite usefulnessGood basis- short, near orthogonal - the private keyb1b2tt in this basis = (1.48, 1.55)round to (1, 2), lattice point (4, 4)distance 1.03 - the true nearest pointBad basis- long, badly skewed - the public keyb1b2tt in this basis = (4.35, -2.88)round to (4, -3), lattice point (2, 0)distance 3.98 - 3.9x too farlattice pointtarget ttrue nearestwhere rounding landedIn the hundreds of dimensions ML-KEM works in (512 to 1024), finding the good basis is the open problem.
The same lattice under a good basis and a bad basis

Both panels show the identical point set. The bases are related by the unimodular matrix [[1,3],[1,4]] (determinant 1), so they generate exactly the same lattice. Now run Babai's rounding algorithm. Express the target in the basis, round each coordinate, and return that lattice point.

  • The good basis is short and near orthogonal. It rounds (1.48, 1.55) to (1, 2), landing at (4, 4) at distance 1.03. That is genuinely the closest point.
  • The bad basis is long and skewed. It rounds (4.35, -2.88) to (4, -3), landing at (2, 0) at distance 3.98. Nearly four times worse, same algorithm.

Publish the bad basis, keep the good one. That is a public/private keypair made of nothing but geometry. In two dimensions you could find the good basis by inspection. In the 512 to 1024 dimensions ML-KEM works in, with LLL resistant parameters, nobody knows how.

Learning With Errors

Modern schemes phrase this as noisy linear algebra rather than raw geometry:

b = A*s + e (mod q)A - public4111105595390101332xs - secret????+e - tiny noise+1-1+10=b - published208115e = 0Gaussian eliminationrecovers s in milliseconds.e != 0every row becomes anapproximation; recovery= closest vector problem.Kyber and Dilithium use the module variant: entries are polynomials in Z_q[X]/(X^256+1), not scalars,which shrinks the public matrix from n^2 numbers to k^2 polynomials - the reason the keys are kilobytes, not megabytes.ML-KEM: q = 3329, n = 256, k in {2,3,4} | ML-DSA: q = 8380417, n = 256
Learning With Errors as a noisy linear system

Publish A and b = A*s + e (mod q) where s is secret and e is small noise. Set e = 0 and Gaussian elimination recovers s in milliseconds. Add the noise and every equation becomes an approximation. Recovering s is then equivalent to finding a close vector in a lattice.

Regev's 2005 reduction is what makes this trustworthy. An algorithm for average case LWE would give a quantum algorithm for approximate shortest vector problems on every lattice. That worst case guarantee is something factoring has never had, though concrete parameters are still set by cryptanalysis rather than by the reduction.

Module-LWE: why the keys are kilobytes and not megabytes

Plain LWE needs an n x n public matrix. For n = 256 that is 65,536 coefficients. Kyber and Dilithium use the module variant, where entries are polynomials in Zq[X]/(X256+1)\Z_q[X]/(X^{256}+1) and the matrix is only k×kk \times k with k∈{2,3,4}k \in \{2,3,4\} (k×ℓk \times \ell for ML-DSA). A single seed ρ\rho regenerates A^\hat{A} via SHAKE, so the matrix is never transmitted at all.

code
ML-KEM:  q = 3329,     n = 256,  k = 2/3/4
ML-DSA:  q = 8380417,  n = 256,  (k,l) = (4,4)/(6,5)/(8,7)

Both moduli are chosen so the number theoretic transform applies, making polynomial multiplication O(nlog⁡n)O(n\log n) instead of O(n2)O(n^{2}). That is why post quantum operations are fast even though the objects are large.

The two moduli are not equally lucky, though, and the difference falls out of the factorisation of q−1q-1. The NTT needs roots of unity, and how many the field contains is decided by which powers of two divide q−1q-1:

ML-KEM (Kyber)ML-DSA (Dilithium)
Modulusq=3329q = 3329q=8380417q = 8380417
q−1q-1 factors as28⋅132^{8}\cdot 13213⋅10232^{13}\cdot 1023
Powers of two available256∣q−1256 \mid q-1, but 512∤q−1512 \nmid q-1512∣q−1512 \mid q-1
So X256+1X^{256}+1 splits into128 quadratics256 linear factors
Transform"incomplete" NTTfull NTT
Pointwise products128, each in Zq[X]/(X2−ζ)\Z_q[X]/(X^{2}-\zeta)256 scalar multiplications

Kyber's smaller modulus buys tighter ciphertexts at the cost of stopping one level short in the transform. It cannot finish splitting the ring, so its pointwise stage multiplies pairs of linear polynomials rather than plain field elements. It is a deliberate trade rather than an oversight.

Part IV. The comparison, in numbers

Public keys

X25519 / Ed25519128 bit classical32 BRSA-3072128 bit classical384 BML-KEM-768 (ek)NIST level 31,184 BML-DSA-65NIST level 31,952 BML-DSA-87NIST level 52,592 BPost quantum public keys are 37-81x an elliptic curve key. That is the price of the transition, paid inbandwidth.
Public key sizes compared

What actually goes on the wire

Ed25519 signature64 BRSA-3072 signature384 BML-KEM-768 ciphertext1,088 BML-DSA-65 signature3,309 BML-DSA-87 signature4,627 BAn ML-DSA-87 signature is 72x an Ed25519 one - enough to change how you design a token, not whether you can.
Signature and ciphertext sizes compared

An ML-DSA-87 signature is 4,627 bytes - 72x an Ed25519 signature. That is enough to change how you design a token format, but not whether you can have one. The signature is not even the biggest part. A UCAN names its principals as did:key strings, and an ML-DSA-87 did:key embeds the whole 2,592 byte public key. Measured with our pq-ucan crate, a delegation between two ML-DSA-87 principals is about 15 KB of DAG-CBOR and 20 KB once base64url encoded, against 532 bytes for the same token signed with Ed25519. The practical consequence is "put it in a header or body, never a URL, and refer to keys rather than inlining them", not "impossible".

Speed, measured

Mean times from aws-lc-rs on an Apple M4 Pro. Your hardware will differ, and the shape will not.

OperationEd25519RSA-3072ML-DSA-65ML-DSA-87
Keygen~6 us~118 ms~24 us~36 us
Sign~5 us~0.9 ms~63 us~82 us
Verify~18 us~19 us~20 us~33 us

Note the shape: RSA verification is fast (small exponent), signing is slow. Verification is a three way tie at about 20 us, and ML-DSA signing, while roughly fourteen times Ed25519, still finishes in under a tenth of a millisecond. The post quantum penalty is bandwidth rather than compute, which is the opposite of what most people assume.

Part V. What a quantum computer does

Shor's algorithm solves both factoring and discrete logarithms in polynomial time. That is not merely faster. It is polynomial, a different complexity class. RSA and ECC do not get weaker. They stop existing as security assumptions.

ECC-256 (Curve25519)Fewest, on classic estimatesabout 2,330 logical qubitsRSA-2048Larger operands, more qubitsabout 4,099RSA-3072about 6,150ML-KEM / ML-DSAno known polynomial attackRoetteler et al. (2017) and Beauregard (2003). Gidney (2025) cuts RSA-2048 much further. Physical counts areorders of magnitude higher.
Logical qubits required to break each primitive

The ordering surprises people. On the classic estimates, elliptic curves fall first. A 256 bit curve needs roughly 2,330 logical qubits against RSA-2048's 2n + 3 = 4,099, because the operands are smaller. The primitive with the better classical security ratio has the worse quantum one. Newer RSA specific constructions (Gidney, 2025) have narrowed that gap considerably, so plan as if both fall together.

Grover's algorithm, meanwhile, gives only a quadratic speedup against symmetric primitives, so AES-256 retains 128 bit security. Symmetric cryptography was never the problem. The entire migration is about public key operations.

For lattices, no polynomial time quantum algorithm is known for SVP or CVP. The best quantum attacks are modest improvements on classical sieving. That is an absence of evidence rather than a proof, and it is the honest reason to prefer hybrids during the transition.

Part VI. Choosing, in practice

Harvest now, decrypt later is the deciding argument. An adversary recording encrypted traffic today can decrypt it whenever a cryptographically relevant quantum computer arrives. For data with a confidentiality horizon measured in decades, such as clinical trials, genomic cohorts, and national security, the transition deadline is not when quantum computers arrive. It is today.

Signatures are different. A signature only needs to resist forgery while it is still being relied upon. Signing an archive again later is feasible in a way that reencrypting intercepted traffic is not.

That asymmetry gives a clean rule:

  • Encrypt with post quantum protection now - the risk is retroactive.
  • Sign with a hybrid, and migrate on your own schedule.

A hybrid signature concatenates both and accepts only if both verify. The "either" variant you sometimes see proposed is strictly worse than the stronger algorithm alone, because an attacker who breaks the weaker one forges freely.

This is the reasoning behind our own stack, which follows the rule above. Encryption is post quantum today. ML-KEM-1024 wraps the AES-256-GCM content key of every stored file. Signatures are not yet. Capability tokens, DID control and browser session keys are Ed25519, because the wallet that signs them is a Solana wallet. ML-DSA-87 is supported by pq-ucan, is a did:bio verification method type, and is the assertion key the service's own did:bio carries once registered, but it does not sign user tokens - documented honestly, including what is not yet post quantum.

The one paragraph version

RSA is hard because factoring is subexponential, which forces enormous keys and a key generation procedure that searches rather than derives. Elliptic curves are hard because the discrete log is fully exponential, which is why 32 bytes suffices. Lattices are hard because a bad basis makes an easy geometric problem intractable, and that hardness has no known quantum shortcut. The first two are elegant and doomed. The third is bulky and survives. Bandwidth is a cheaper thing to spend than time you do not have.


Further reading: FIPS 203 (ML-KEM), FIPS 204 (ML-DSA), Regev (2005) on LWE, and our Post Quantum Security documentation.

Ready to Get Started?

Explore our documentation to learn how to integrate Ekayana into your research workflow.