In preparation for this post, I’ve read several research papers, a book, listened to 4 university lectures, idled away hours on IRC, developed elliptic curve libraries in 2 seperate languages, and built my own elliptic curve graphing framework. Elliptic curve cryptography is hard to wrap your head around. As one of the fundamental crypto systems making Bitcoin a “crypto”-currency, I really wanted to understand the underlying technical aspects which make this form of cryptography secure. This post is an attempt to demystify the elliptic curve digital signing algorithm which underlies bitcoin’s psuedo-anonymous identity system.

Explain like I’m 5 (or thereabouts)

Imagine a classroom of elementary school children who know multiplication but have not yet learned division. At the beginning of the year, the teacher proclaims “My special number is 5”. One morning, the message “Twas always thus and always thus will be” – signed “Teacher - 8” appears on the chalkboard. How do the students know this message came from the teacher and not some movie-quote-loving fraudster? They multiply the teacher’s “special number” - 5 - by the “signature number” - 8 - and if they get the number of characters in the message (40 characters), they deem the signature valid, and are confidant that the message actually came from the teacher. Oblivious to the magic of division, students are unable to produce a valid signature for any arbitrary message, and because the signature is based on the length of the message, the students can’t serruptitously change the message.

This is fundamentally how the elliptic curve digital signature algorithm works; the knower of the private key is endowed with the power of division, while public key holders are restricted to multiplication, which lets them check whether a signature is valid.

Why does Bitcoin need digital signatures?

Alice sends 2 bitcoins to Bob’s public bitcoin address (1Bob4ddr355). If Bob sends these 2 bitcoins to Charley (1Char4ddr355), he broadcasts a message stating “1Bob4ddr355 sends 2 BTC to 1Char4ddr355”. The Bitcoin system must ensure that Bob and only Bob can broadcast this message; if anyone can broadcast a transaction spending Bob’s bitcoin, or alter Bob’s message in anyway, then Bitcoin breaks irreparably.

Public Key Cryptography to the Rescue

Bob needs:

a private key - sequence of numbers that only Bob knows

a public key - another sequence of numbers that Bob can share with anyone

a message to be signed

A digital signature system will enable the following: To sign: "This is a message" + Private Key Bob = Signature "This is a message", Bob To verify: "This is a message" + Signature "This is a message", Bob + Public Key Bob = True "Another message" + Signature "This is a message", Bob + Public Key Bob = False "This is a message" + Signature "This is a message", Chuck + Public Key Bob = False "This is a message" + Signature "Another message", Bob + Public Key Bob = False "This is a message" + Signature "This is a message", Bob + Public Key Chuck = False

Because it’s impossible to create Signature “This is a message”, Bob without Bob’s private key, we can be certain that Bob and only Bob digitally signed a message when his public key verifies a signature.

Several mathematical techniques can be used to build such a system, but the current “cutting edge” technology in terms of efficiency and security is elliptic curve cryptography.

What are Elliptic Curves?

Not to be confused with an “ellipse,” elliptic curves look like:

The general equation for elliptic curves is: $$y^2 = x^3 + a*x + b$$ This specific elliptic curve has equation: $$y^2 = x^3 - 3*x + 4$$ All elliptic curves are symmetric about the x-axis.

We need the ability to add 2 points on this curve; which works as follows.

To add 2 points (Point A, and Point B) Draw a line between Point A and Point B This line always intersects the elliptic curve at a 3rd point. Reflect the the observed intersection point over the x axis to get the sum of Point A and Point B (-2.0, 1.4) + ( , ) = ( , ) This graph is interactive, click on the curve to compute different sums.

What happens if we want to add a point to itself? We can’t draw a line between a point and itself, so we slightly modify the above operation.

To double a point (Point A + Point A) Draw a line tangent to the elliptic curve through Point A This line always intersects the elliptic curve at a 2nd point. Reflect the the observed intersection point over the x axis to get 2 * Point A 2 * ( , ) = ( , ) The graph is interactive, click on the curve to compute a different double.

Using a bit of algebra and calculus, we can derive the following equations to easily add or double points without the necessity of graphs. The equations themselves aren’t very interesting; they’re here to show that point addition and doubling are trivially calculated by computers.

Given $(x_1, y_1), (x_2, y_2)$: to find $(x_3, y_3) = (x_1, y_1) + (x_2, y_2)$ $x_3 = s^2 - x_1 - x_2$ $y_3 = s(x_1 - x_3) - y_1$ $$s = \begin{cases} \frac {y_2 - y_1}{x_2 - x_1}, & \text{if $(x_1, y_1)

eq (x_2, y_2)$} \\ \frac {3x^2 + a}{2y_1}, & \text{if $(x_1, y_1) = (x_2, y_2)$} \end{cases}$$

Point addition and point doubling gives us:

$$\text {Point A} + \text {Point B} = \text {Point C}$$ $$2 * \text {Point A} = \text {Point 2A}$$ Because multiplication is just addition many times, we also have multiplication: $$\text {Point A} + \text {Point A} + \cdots + \text {Point A} = N * \text {Point A}$$ $$N * \text {Point A} = \text {Point NA}$$ $$\text {Point A} + \text {Point A} + \cdots + \text {Point A} = N * \text {Point A}$$ $$N * \text {Point A} = \text {Point NA}$$

Let’s say we want to figure out “9 * Point A”….how might we do that?

One way to do this:

2 * Point A = Point 2A

Point 2A + Point A = Point 3A

Point 3A + Point A = Point 4A

Point 4A + Point A = Point 5A

Point 5A + Point A = Point 6A

Point 6A + Point A = Point 7A

Point 7A + Point A = Point 8A

Point 8A + Point A = Point 9A ... our answer.

An easier way: (called the “divide and conquer method”)

2 * Point A = Point 2A

2 * Point 2A = Point 4A

2 * Point 4A = Point 8A

Point 8A + Point A = Point 9A ... our answer.

Using the divide and conquer method, we compute the product in only 4 steps, instead of 9. As the multiplier increases in size, the time saved using the divide and conquer method increases exponentially: calculating 1,000 * G takes only 10 steps and 10,000 * G takes 14 steps (bitcoin uses numbers on the order of 1077, which take about 250 steps to compute). This trick is very important in making elliptic curve cryptography actually work, and is the basis of the public key pair (more on that later).

A problem

Computers hate decimal places, and the preceeding equations produce numbers with decimals. Some decimals are irrational (they go on forever…like 1.4142135623…), and computers don’t have the infinite space required to store all these digits. They can make approximations, but when rounding produces equations that ask if 5.9999999 = 6, what’s the computer to do?

Two relatively esoteric mathematical concepts called “finite fields” and “modular arithmetic” help us solve this problem.

If you can tell time, you already understand some modular arithmetic. If it’s 21:00 (9:00pm), and you must wake up for work in 11 hours, you will set your alarm for 8:00; not 32:00. When the clock resets at 24:00, we continue counting from 0:00. This concept, known as “taking the modulus”, lets us transform fractions and decimals into whole numbers.

If our modulus is 13 (upper limit is 13), and we wish to transform $\color {#a12}{\frac {1}{7}}$: $$\begin{align} 7 * \color {#a12}{\frac {1}{7}} &= 1 \\ 7 * \color {#a12}{2} \text { mod 13} &= 1 \\ \end{align}$$ $$\begin{align} 7 * \color {#a12}{\frac {1}{7}} &= 1 \\ 7 * \color {#a12}{2} \text { mod 13} &= 1 \\ \end{align}$$ Because these equations both equal 1, we can substitute the fraction $\color {#a12}{\frac {1}{7}}$ with the integer $\color {#a12}{2}$ when operating within a finite field.

This technique of transforming fractions into integers is used to eliminate all decimals from the above mathematical equations, making our computer very happy.

Elliptic Curves over Finite Fields

When translating our beloved elliptic curves onto finite fields, graphing all points on the curve becomes a difficult problem. In order to enumerate all points, we add an initial point, called the “generator point” to itself many times.

An elliptic curve with modulus 29 (upper limit is 29) looks like:

Generated Points

Some peculiar things that you might notice:

Graph is symmetric about the line y = 14.5. Like our continuous graphs, each point has a complement on the same x coordinate.

Not every x coordinate has a point (look at x = 10….there are no points)

We’re only able to show all points because the modulus is very small. When using a much bigger modulus, such as the one bitcoin uses, creating a “full graph” of all points is impossible.

Using our trusty equations from above and a convoluted graphing system which wraps around the axes, we can see that our point doubling operator still works properly.

2 * ( , ) = ( , ) ( , ) = * G ( , ) = * G = 2 * mod 31 The graph is interactive, click on any point to compute it's double.

The Key to Elliptic Curves

We’re now ready to discuss public and private keys:

Private key is the generator multiplier (an integer). G is the generator point, it is publicly known and is the same for everyone. Public key is the point generated by the private key. $$\color {#15a} {\text {Private Key}} * G = \color {#59d} {\text {(Public Key)}}$$

Some intersting things arise from this arrangement:

If the private key is very large, it’s easy to compute the public key using the divide and conquer method, but very difficult for an attacker to brute force.

Unlike the public key, the private key is just a number. We’re able to perform “normal” math operations on it to build out the digital signature system (we can easily divide, multiply, etc.)

The public key, an elliptic curve point, is restricted to the addition and doubling operations that we’ve discussed (there is no division of points)

We now have a system fairly similiar to the elementary school classroom scenario above.

The Digital Signature Algorithm

The signer creates 3 points:

Message Point : Convert the message to a number (by taking it’s hash), and multiply this number by the generator point

(Message Point) = Message Hash * G Random Point : We pick a point at random

(Random Point) = Random Number * G Random-Public Key Point : We multiply the x-coordinate of the random point by the public key, (remember, the random point’s x coordinate is an integer)

(PK-Random Point) = Random Point X-Coordinate * (Public Key)

The signer creates a special pathway to the “Random Point” by way of both the “Message Point” and the “PK-Random Point”. We must compute a signature factor such that

$$(\color {#a12}{\text {Signature Factor}} * \color {#629}{\text {Message Point}}) + (\color {#a12}{\text {Signature Factor}} * \color {#15a}{\text {Random Public Key Point}}) = \color {#084}{\text {Random Point}}$$

The signer then gives the random point and the signature factor to the verifier, who checks whether the signature factor recreates the special pathway to the random point by way of the “Message Point” and “PK-Random Point.”

This is secure because:

Creating a signature factor that verifies with a given public key is impossible to create without the knowledge of the public key’s generator.

The signature factor is also used in conjunction with the message hash, so if the message ever changes, the signature factor will no longer be useful in recreating the “pathway” to the given random point. As stated above, creating a new signature factor to work with a modified message is out of the question.

Hopefully the following example can help illuminate this process further (although, admittedly, it’s a bit hard to conceptualize). Notice when the verifier changes any of the parameters, the signature is no longer valid.

The Signer The signer knows: Generator: 1 * G = (0, 2) Private Key: 7 * G = (17, 9) Random Point: 9 * G = (13, 25) Message Hash: 14 Signature Factor: $$\color {#a12}{22} = \frac {\color {#426}{14} + \color {#084}{13} * \color {#147}{7}}{\color {#042}{9}}\text{ mod 31}$$ The Signature 22 , 13 The Verifier The verifier knows: Generator: 1 * G = (0, 2) Public Key: (17, 9) (0, 2) (6, 17) (22, 1) (23, 3) (2, 8) (7, 6) (21, 3) (13, 25) (3, 15) (19, 22) (14, 26) (28, 8) (8, 17) (15, 17) (15, 12) (8, 12) (28, 21) (14, 3) (19, 7) (3, 14) (13, 4) (21, 26) (17, 20) (7, 23) (2, 21) (23, 26) (22, 28) (6, 12) (0, 27) Signature Factor: 22 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 23 24 25 26 27 28 29 30 Message Hash: 14 1 2 3 4 5 6 7 8 9 10 11 12 13 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 Message Verification Point: $$ \color {#629}{(2, 21)} = \frac {\color {#426}{14}}{\color {#a12}{22}}\text{ mod 31 } * (0,2) $$ Public Key Verification Point: $$ \color {#15a}{(8, 17)} = \frac {\color {#084}{13}}{\color {#a12}{22}}\text{ mod 31 } * \color {#147}{(17, 9)}$$ Verification Point: $$ \color {#629}{(2, 21)} + \color {#15a}{(8, 17)} = \color {#084}{(13, 25)}$$ The verification point equals the signer's random point. This signature is valid.

Bitcoin Numbers

To ground all this in reality, here are some real numbers taken directly from bitcoin itself (bitcoin uses the sicp256k1 curve, which has it’s own paramers and generator point).

Generator Point: Remember, this is the same for everyone. All other points are children of this base point.

x: 55066263022277343669578718895168534326250603453777594175500187360389116729240 (10^76)

y: 32670510020758816978083085130507043184471273380659243275938904335757337482424 (10^76)

Order: The number of possible points on the curve. There’s a nifty formula which calculates this (I have no idea why it works, but it does)

115792089237316195423570985008687907852837564279074904382605163141518161494337 (10^77)

Private Key:

23695310554196047209792918797392416191148132060917476866274911959533140016553

Public Key:

x: 39874617776630327813190058413816560767734954098998567043224950074533143699292

y: 83115399533222200534442050051826386603242609920409430626876080623730665355556

Signature:

r: 25282362915497655056329512917121654088602539327808216077267936411779996643728

s: 39257440409490934652644589859771879805788241064351461738307073788061051966857

These are truly gargantuan numbers - the number of possible points on the elliptic curve is fairly close to the number of atoms in the observable universe. A human body contains 7,000,000,000,000,000,000,000,000,000 atoms. Think about how insignificant in size we are compared to the entire earth, which is insignificant compared to the sun, which is only 1 of hundreds of billions in a single galaxy, of which there are hundreds of billions in the universe. Computers are fast, but not fast enough to visit even a small fraction of those points. It’s just impossible. It’s amazing that such security is possible so quickly and accessibly (a phone can do these calculations in fractions of a second); full acollades go out to the brilliant cryptographers, mathematicians, and computer scientists behind the elliptic curve technology.

Key Take-aways

An elliptic curve is nothing more than: Point = Multiplier * Public Generator Point

Private key is the multiplier, public key is the point

Given the point, it’s impossible to get the multiplier

You can do addition, subtraction, multiplication, and division with the multiplier (private key); but can only do addition and multiplication with the point (public key)

Creating a signature requires division (needs the private key), but verifying the signature only needs addition and multiplication (can be done with public key)

Special Thanks to the following resources which helped me out immensely: