ECDSA and Bitcoin III: Private Key, Public Key and Address

If we have an elliptic curve(defined by aa and bb), a prime(PP), an basepoint G(x1,y1)G(x1,y1) and an order of this basepoint(NN), then we can choose a number(say nn) and calculate nGn*G.
nn is sometimes called private key and nGn*G is sometimes called public key.

An example

Parameters

a = 1; b = 1; P = 23;
x1 = 3; y1 = 10; G = [x1,y1];
N = 28;

The above example has only 27 possible private keys(N1=27N-1=27). It’s not safe. We need a large NN, say

N=115792089237316195423570985008687907852837564279074904382605163141518161494337N = 115792089237316195423570985008687907852837564279074904382605163141518161494337

That’s the order of Bitcoin.

Bitcoin

1. Private key and public key

Parameters

a =0; b = 7; P = 2256232292827262412^{256} - 2^{32} - 2^{9} - 2^{8} - 2^{7} - 2^{6} - 2^{4} -1;
x1 = 79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
y1 = 483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
G = [x1,y1];
N = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141

Python Gist

If you want to do it in Python, this is my gist.

Tips: dealing with big numbers in JavaScript is tedious and the result of modular(%) may be negative in JavaScript while In Python it’s always positive.

More info: ref1, ref2, ref3, ref4, ref5, ref6

In the real world, the private key still needs to be converted to Wallet Import Format(WIF). Also public key needs to be converted to address.

2. From private key to WIF

Suppose we’ve chosen a private key:

59748189462850000000000000000000000000000000000000000000000000000000000000000

2.1 Its hexdecimal form:

Private key(hex): PK0 = 841846de7afbe32ee7ded837872c6e0825db095275b8afed0000000000000000

2.2 Add “0x80” to the head of PK0:

PK1 = 80841846DE7AFBE32EE7DED837872C6E0825DB095275B8AFED0000000000000000

Here “0x” indicates this “80” is a hexdecimal number rather than a decimal number.

2.3 SHA-256(PK1):

PK2 = 185C164F93FA16C66019E15356AA2DE9674AD310B0D8A45747657F3079172815

2.4 SHA-256(PK2):

PK3 = 66FCA214401C8C61C5490FDD14D259877F21A86E9D1A26596E75F69770A678AB

2.5 Checksum(first 8 hexadecimal digits/4 bytes of PK3):

66FCA214

1 hexdecimal digit = 4 bits && 1 byte = 8 bits --> 2 hexdecimal digits = 1 byte -->
8 hexadecimal digits = 4 bytes
More info: Hexadecimal numeral system

2.6 Add Checksum to the tail of PK1:

PK4 = 80841846DE7AFBE32EE7DED837872C6E0825DB095275B8AFED000000000000000066FCA214

2.7 Base58 encoding of PK4:

WIF = 5JpTmRPSNsrt2EptGiR2pcJ7xZGQeCVvTRfpQr4XD4om8dsB8Ew

Base58 alphabet: “123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz”.
Compared to Base64, the following similar-looking letters are omitted: 0 (zero), O (capital o), I (capital i) and l (lower case L) as well as the non-alphanumeric characters + (plus) and / (slash).

3. From public key to address

Still, suppose we’ve chosen the private key:

59748189462850000000000000000000000000000000000000000000000000000000000000000

3.1 After Elliptic Curve Multiplication we get:

Public key(hex): UK0 = 3a56bd64573c28050bfe202c57e56b46c63744a253d1430e2b737876fa883b19,73c2f565444dc62151562993ff4b566c826010befb289fa2fc749293266066c0

3.2 Add “0x40” to the head of UK0:

UK1 = 043a56bd64573c28050bfe202c57e56b46c63744a253d1430e2b737876fa883b1973c2f565444dc62151562993ff4b566c826010befb289fa2fc749293266066c0

Again here “0x” indicates this “40” is a hexdecimal number rather than a decimal number. You may noticed two parts of UK0(value of horizontal axis and value of vertical axis) are put together.

3.3 SHA-256(UK1):

UK2 = c41dde43a4f6dd7aa0354150c784bbc8356cb8617ff685b6fc3f8287c826759f

3.4 RIPEMD-160(UK2):

UK3 = aa3dc7fda0e233b71a53938e7ae42bf5a583fc8c

3.5 Adding “0x00” to the head of UK3:

UK4 = 00aa3dc7fda0e233b71a53938e7ae42bf5a583fc8c

“0x00” stands for Mainnet while “0x6F” stands for Testnet.
More info: ref1, ref2

3.6 SHA-256(UK4):

UK5 = bef81c4a971778759545b3d3816765c437d5ab964df77e3e356ffc8b9a2d0af4

3.7 SHA-256(UK5):

UK6 = 6be6d3cfdb5464f3aca1777400be94dc500a8bb84a5cf25d968721c7a850d2cf

3.8 Checksum(first 8 hexadecimal digits/4 bytes of UK6):

6be6d3cf

3.9 Add Checksum to the tail of UK4:

UK7 = 00aa3dc7fda0e233b71a53938e7ae42bf5a583fc8c6be6d3cf

3.10 Base58 encoding of UK7:

Address = 1GX9tFDj3mBj7NBL6rDtqcnh1ZzPetqF9x

More info: ref1, ref2, ref3, ref4

4. Try it you self

Open it in a new tab

5. Python gist

From private key to WIF

From public key to address

More info: freecodecamp, blocksmith, python-ecdsa, Python doc