§ 02

§ 02 · Cryptography

Elliptic curves

Easy to multiply, impossible to divide

Your Pearl private key is just a huge random number. Your public key is a point on a curve, made from that number. The magic is that the step from one to the other only works in one direction.

That one-way step is the arithmetic of an elliptic curve. Pearl uses the same curve as Bitcoin, called secp256k1. This page builds the idea on a tiny toy curve you can check by hand, then scales it up.

Try it

Pick two points and add them, or multiply a point by a number, and watch the result jump around the dots.

Toy elliptic curve

y² = x³ + 7, the same equation as Pearl’s keys, on a tiny grid

001122334455667788991010111112121313141415151616QP−(P+Q)P+Q

(6, 6) + (1, 5)

= (8, 14)

Draw the line through P and Q (the shaded cells; on a grid mod 17 a line wraps around the edges). It hits exactly one more curve point, −(P+Q). Flip it across the middle line to get P + Q.

Field
0 … 16, mod 17
Points
18 (17 + O)
G
(6, 6)
Order of G
18

The real thing: secp256k1, the same equation over a prime of about 2²⁵⁶. It has about 1.16 × 10⁷⁷ points, far too many to draw or to search.

Runs in your browser · a toy, not real keys src/lib/keys.ts · toyCurve

What is an elliptic curve?

It’s the set of points (x, y) that satisfy one equation. Pearl’s curve uses about the simplest one possible:

y2=x3+7(modp)y^2 = x^3 + 7 \pmod p
secp256k1

Over ordinary numbers that draws a smooth curve. But cryptography uses whole numbers with modular arithmetic, where everything wraps around at a prime p, like a clock. With p = 17, for example, 15 + 5 = 20 wraps to 3.

On a toy curve with p = 17, only 17 points (x, y) fit the equation. Add one special point, the “point at infinity”, which plays the role of zero, and there are 18 points in all.

051015051015y = 8.52G16G14G4G9G12G6GG17G15G3G13G5G8G10G7G11G
The toy curve y² = x³ + 7 mod 17: seventeen dots, mirrored around the middle line y = 8.5. Each dot is labelled by which multiple of G = (6, 6) it is.

How do you add two points?

Geometrically: draw a straight line through the two points. It crosses the curve at exactly one more point. Flip that point to the other side (negate its y) and you have the sum.

To add a point to itself (“doubling”), use the tangent line at that point instead. And adding a point to its mirror image gives the point at infinity, the zero of this arithmetic.

On a modular curve there’s no picture to draw, but the same rule becomes a formula. Here is G + 2G on the toy curve, with G = (6, 6) and 2G = (1, 5), all arithmetic mod 17:

  1. The slope

    λ=y2−y1x2−x1=5−61−6=−1−5=15\lambda = \dfrac{y_2 - y_1}{x_2 - x_1} = \dfrac{5 - 6}{1 - 6} = \dfrac{-1}{-5} = \dfrac{1}{5}. Dividing by 5 mod 17 means multiplying by 7, because 5 × 7 = 35 = 2 × 17 + 1. So λ = 7.

  2. The new x

    x3=λ2−x1−x2=49−6−1=42≡8x_3 = \lambda^2 - x_1 - x_2 = 49 - 6 - 1 = 42 \equiv 8
  3. The new y

    y3=λ(x1−x3)−y1=7⋅(6−8)−6=−20≡14y_3 = \lambda(x_1 - x_3) - y_1 = 7 \cdot (6 - 8) - 6 = -20 \equiv 14
  4. Check

    (8, 14): 14² = 196 ≡ 9, and 8³ + 7 = 519 ≡ 9. On the curve. That’s 3G.

Doubling G by hand

For doubling, the slope comes from the tangent: λ=3x122y1=3⋅3612=10812\lambda = \dfrac{3x_1^2}{2y_1} = \dfrac{3 \cdot 36}{12} = \dfrac{108}{12}. Mod 17, 108 ≡ 6, and dividing by 12 means multiplying by 10 (12 × 10 = 120 ≡ 1), so λ = 60 ≡ 9.

Then x3=81−12=69≡1x_3 = 81 - 12 = 69 \equiv 1 and y3=9⋅(6−1)−6=39≡5y_3 = 9 \cdot (6 - 1) - 6 = 39 \equiv 5. So 2G = (1, 5), as the figure shows.

What does it mean to multiply a point?

Multiplying G by a number k means adding G to itself k times: 3G = G + G + G. Here are all the multiples on the toy curve:

k 1 2 3 4 5 6 7 8 9
kG (6,6) (1,5) (8,14) (2,10) (10,15) (5,9) (15,4) (12,1) (3,0)
k 10 11 12 13 14 15 16 17 18
kG (12,16) (15,13) (5,8) (10,2) (2,7) (8,3) (1,12) (6,11) ∞

At 18 it wraps back to the point at infinity and starts again. The number of steps before the wrap, 18 here, is called the order.

This is exactly how keys work. Pick a secret number, say 5: that’s the toy private key. Multiply the generator point: 5G = (10, 15). That’s the toy public key.

For a real 256-bit key, adding G to itself trillions of trillions of times would take forever. Computers use double-and-add instead: write k in binary, double for every bit and add G for every 1 bit. A 256-bit key takes about 256 doublings, which is instant.

Why can’t anyone work backwards?

Going from 5G back to 5 means asking “how many times was G added?” That’s the discrete logarithm problem.

On the toy curve it’s trivial: try G, 2G, 3G… and you’re done within 18 steps. Nothing smarter is needed. On secp256k1 the same search has about 10⁷⁷ steps, and the best known methods only take that down to about 2¹²⁸ steps, still far beyond every computer on Earth. That gap between “easy forwards” and “impossible backwards” is what keeps a private key private.

What are secp256k1’s real numbers?

secp256k1 is the toy curve with enormous numbers. Same equation, y² = x³ + 7:

Parameter Value
p (the modulus) fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
n (the order of G) fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
G, x-coordinate 79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798

A private key is any number from 1 to n − 1, about 1.16 × 10⁷⁷ choices. Its public key is that number times G. Here are the first three, computed with this site’s code:

Private key Public key (compressed, 33 bytes)
1 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
2 02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5
3 02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9

Private key 1 gives G itself. Nobody should use these keys: anyone can compute them.

How is a point written down?

A point is two 32-byte numbers, x and y. Pearl writes it in one of two short forms:

  • Compressed, 33 bytes: a prefix 02 or 03 saying whether y is even or odd, then x. Used in extended keys and fingerprints.
  • X-only, 32 bytes: just x, with y assumed even. Everything on chain uses this: Taproot output keys, Schnorr signatures and tapscript keys.

Each x has only two possible y values (y and p − y, one even, one odd), so the short forms lose nothing.

Code: the toy curve in JavaScript

The arithmetic above, for y² = x³ + 7 over a small prime p. null is the point at infinity.

JavaScript
const p = 17;
const mod = (a) => ((a % p) + p) % p;
const inv = (a) => { let r = 1, b = mod(a), e = p - 2; while (e) { if (e & 1) r = (r * b) % p; b = (b * b) % p; e >>= 1; } return r; };

function add(P, Q) {
  if (!P) return Q;
  if (!Q) return P;
  if (P.x === Q.x && mod(P.y + Q.y) === 0) return null;          // P + (−P) = ∞
  const l = P.x === Q.x
    ? mod(3 * P.x * P.x * inv(2 * P.y))                          // tangent (doubling)
    : mod((Q.y - P.y) * inv(Q.x - P.x));                          // chord
  const x = mod(l * l - P.x - Q.x);
  return { x, y: mod(l * (P.x - x) - P.y) };
}

add({ x: 6, y: 6 }, { x: 1, y: 5 });   // { x: 8, y: 14 } = 3G

pearld gets the real curve from the decred secp256k1 library, in btcec.go (node/btcec/btcec.go:23-41 at v1.5.2, on GitHub).

The codex

Suggested

Up and down arrows move through the results, Enter opens one, Escape closes. Anywhere on the site, slash or Command K opens this search, and the square brackets [ and ] go to the previous and next page.