Bitcoin’s Cryptography Explained — Article 4 of 5

Bitcoin’s Cryptography Explained — Bitcoin’s Curve

The Ellitptic Curve of Bitcoin

Block 871,747|~5 min read

by Jonas Benner

In the first three articles of this article series on the cryptography behind Bitcoin we learned about fintie fields, elliptic curves over real numbers and the combination of the two, elliptic curves over finite fields. These are the fundamental building blocks of elliptic curve cryptography (ECC). In this article we will have a look at the elliptic curve that Bitcoin uses and what private and public keys actually are and how they work. This is the point where we properly connect what we learned in the first three articles to Bitcoin and will shed a lot of light on what a private and public key are at a fundamental level.

Bitcoin’s Elliptic Curve

The cryptographic (elliptic) curve that Bitcoin uses is called “secp256k1”. This curve is defined by the following parameters:

Curve equation: y2 = x3 + 7

Prime order of the finite field: 2256 - 232 - 29 - 28- 27 - 26 - 24 - 1

Generator point, G, with x- and y-coordinates:

x = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798

y= 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8

Order of generator point, G:

n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141

The prime order, p, can also be written as 2256 - 232 - 977.

The values for x, y and n are written in hexadecimal representation rather than decimal. This is a more compact representation of large numbers and hexadecimal representation has become a sandard for representing large numbers in cryptography. This includes things like public and private keys, hashes and other cryptographic values. Using hexadecimal ensures consistency and interoperability across different systems and platforms that implement cryptographic protocols. But in the end, these values just represent astronomically large integer values.

Also note that both p and n are very close to 2256.

Putting 2256 in perspective

Remember that n is the order of the generator point, which means that there are n−1 affine points on the elliptic curve used in Bitcoin, or n points when we include the point at infinity. The order of the generator point used for Bitcoin’s elliptic curve is close to 2256. Because 2256, which is roughly 1077 is not a number that most people can comprehend, here are some comparisons that put it into perspective (source: Programming Bitcoin by Jimmy Song):

Number of atoms in and on Earth: 1050 Number of atoms in the solar system: 1057

Number of atoms in the Milky Way: 1068

Number of atoms in the observable universe: 1080

A trillion computers doing a trillion computations every trillionth of a second for a trillion yars is still less than 1056 computations

The reason that this is important will become apparent once we’ve seen what private and public keys are.

Private and Public Keys

In essence, the private key, d, is just a large integer in the range [1, …, n−1] that is securely and randomly generated.

The public key, Q, is simply the point on the elliptic curve that is the result of point multiplying the generator point, G, with the private key (i.e. adding the generator point to itself d-1 times):

Q = dG

As we learned in the lesson on elliptic curves over finite fields, if we know d and G it’s really easy to compute Q but if we only know G and Q, it’s practically impossible to solve for d. This is the Elliptic Curve Discrete Logarithm Problem (ECDLP) and it’s the reason why elliptic curve cryptography on the Bitcoin blockchain is so secure. No practical classical attack on securely generated secp256k1 keys is known. This is a computational security assumption, not a guarantee of unbreakable mathematics; secure key generation, storage and signing also matter. Truly incredible.

Here’s some Pyhton code that creates an example private key and computes the corresponding public key:

# Define the field before creating its elements
p = 2 ** 256 - 2 ** 32 - 977
 
# Define the Bitcoin curve
a = FiniteFieldElement(0, p)
b = FiniteFieldElement(7, p)
btc_curve = EllipticCurve(a, b)
 
# Create the generator point
p = 2 ** 256 - 2 ** 32 - 977
G_x = FiniteFieldElement(0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798, p)
G_y = FiniteFieldElement(0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8, p)
generator = ECPoint(G_x, G_y, btc_curve)
 
# Define a private key
private_key = int.from_bytes(b'Satoshi Nakamoto', 'big')
print(f'Private key as integer: {private_key}')
 
# Compute the public key
public_key = private_key * generator
print(f'Public key: {public_key.x.num, public_key.y.num}')
Private key as integer: 110831938034982959267213124394594301039
Public key: (9189960675685860389423310802391916115592466696906485832633579783307896203399, 91239177961079355031999187374243160150596276681847926269292121519844954103361)

Please note that in the above example I just created an example private key by converting the bytes of the string “Satoshi Nakamoto” to an integer and using that as the private key. This is really insecure for many reasons and one should never create a private key to use for actual Bitcoin transactions like this!

The code prints the integer that this private key represents as well as the (x, y) corridnate pair of the public key, i.e. the result of point multiplying the generator point with the private key (large integer).

We can even check the address of this public key on a blockchain explorer such as https://blockexplorer.one/bitcoin/mainnet for the mainnet and https://blockexplorer.one/bitcoin/testnet for the testnet. This Pyhton code converts the public key coordinates into valid Bitcoin addresses:

print(f'Mainnet address of public key: {public_key.address()}')
print(f'Testnet address of public key: {public_key.address(testnet=True)}')
Mainnet address of public key: bc1qrtzagksylmy3ft0rej2u56vzt4qfzuhrkyekrq
Testnet address of public key: tb1qrtzagksylmy3ft0rej2u56vzt4qfzuhruzz9cn

These P2WPKH addresses use the compressed public key. The address shown in the original explorer snapshot was derived from an uncompressed key and has been replaced here; no balance or transaction history is implied.

Why 2256 is important for public key cryptography

Earlier we put 2256 into perspective and showed how astronomically large of a number it is. The fact that the order, n, of the generator point is close to 2256 is important because it means that the private key that you use to generate your public Bitcoin address (which identifies a spending condition for Bitcoin transaction outputs) can be any random integer from 1 to n−1.

This means that there are so many possible values that you could’ve used to compute your public key that it’s impossible to try all the possible values and thereby “steal” your keys and your Bitcoin. Exhaustively guessing a private key is like asking someone to pick a random atom from all the atoms in a billion galaxies, then scrambling those atoms up completely randomly, also choosing an atom at random and ending up with the same atom. Good luck… Generic classical attacks do better than exhaustive guessing, requiring roughly √n operations, which is still around 2128 for secp256k1.

Finally Ready for Cryptography

Now that we have a detailed understanding of elliptic curves over finite fields and the most important operation on them, point multiplication, and we understand the specific curve that Bitcoin uses we are ready to look at the algorithm that allows us to sign Bitcoin transactions using the private key in a way that anyone can verify that signature using our public key. Exciting!

Bitcoin’s Cryptography Explained — Elliptic Curve Cryptography

The Magic behind Bitcoin Transactions