This is an example of a bitcoin address: 14NWDXkQwcGN1Pd9fboL8npVynD5SfyJAE
CONCEPT:- Elliptic Curves
https://www.certicom.com/content/certicom/en/ecc-tutorial.html
Each address corresponds to a point on the elliptic curve secp256k1 (y^3=x^2+7 mod p) where prime p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
The point for the above address as a decimal point on a graph:
(91519190036866233587583752863966343541024156557754641198598352460350806215674, 18110675123485594228049867696927871008716109164646265340106239137304742587157)
to check this is on the curve we can do:
>>> x=91519190036866233587583752863966343541024156557754641198598352460350806215674
>>> y=18110675123485594228049867696927871008716109164646265340106239137304742587157
>>> p=115792089237316195423570985008687907853269984665640564039457584007908834671663
>>> ((y2)%p)==((x3+7)%(p))
True
So how do we get from the point to the address?
CONCEPT: HEX, ripemd150, sha256, base58
First lets convert it to hexadecimal:
>>> x = 91519190036866233587583752863966343541024156557754641198598352460350806215674
>>> x2 = x.to_bytes(32, ‘big’).hex().encode()>>> y = 18110675123485594228049867696927871008716109164646265340106239137304742587157
>>> y2 = y.to_bytes(32, ‘big’).hex().encode()
>>> print(“(“,x2, “, “, y2, “)”)
( b’ca5606a1e820e7a2f6bb3ab090e8ade7b04a7e0b5909a68dda2744ae3b8ecbfa’ , b’280a47639c811134d648e8ee8096c33b41611be509ebca837fbda10baaa1eb15′ )
- Uncompressed SEC Format <0x04><x coordinate in 32 byte big endian hex><y coordinate in 32 byte big endian hex>
>>> r = “04ca5606a1e820e7a2f6bb3ab090e8ade7b04a7e0b5909a68dda2744ae3b8ecbfa280a47639c811134d648e8ee8096c33b41611be509ebca837fbda10baaa1eb15”
>>> rr = bytes.fromhex(r)
>>> rr
b”\x04\xcaV\x06\xa1\xe8\xe7\xa2\xf6\xbb\xb0\x90\xe8\xad\xe7\xb0J~\x0bY\t\xa6\x8d\xda’D\xae\x8e\xcb\xfa(\nGc\x9c\x81\x114\xd6H\xe8\xee\x80\x96\xc3;Aa\x1b\xe5\t\xeb\xca\x83\x7f\xbd\xa1\x0b\xaa\xa1\xeb\x15″
>>> rr.hex()
‘04ca5606a1e820e7a2f6bb3ab090e8ade7b04a7e0b5909a68dda2744ae3b8ecbfa280a47639c811134d648e8ee8096c33b41611be509ebca837fbda10baaa1eb15‘ - Compressed SEC format <0x02 or 0x03><x coordinate in 32 byte big endian hex>
For every value (x, y) on the Elliptic curve the value (x, p-y) is also on the curve so we can encode the y value as even or odd
03ca5606a1e820e7a2f6bb3ab090e8ade7b04a7e0b5909a68dda2744ae3b8ecbfa - WIF Format this is described in this diagram –
i) take the uncompressed sec format address
04ca5606a1e820e7a2f6bb3ab090e8ade7b04a7e0b5909a68dda2744ae3b8ecbfa280a47639c811134d648e8ee8096c33b41611be509ebca837fbda10baaa1eb15
ii) sha256 the long address, followed by ripemd160 -> 20 bytes
>>> hashlib.new(‘ripemd160’, hashlib.sha256(rr).digest()).digest().hex()
’24f98038e995ee03c4178bccaff1652223eba473‘
iii) append 00 prefix byte to this -> 21 bytes
‘0024f98038e995ee03c4178bccaff1652223eba473‘
iv) sha256 these 21 bytes twice and output the first 4 bytes of the output -> 4 bytes
>>> rrr = “0024f98038e995ee03c4178bccaff1652223eba473”
>>> rrrr=bytes.fromhex(rrr)
>>> hashlib.sha256(hashlib.sha256(rrrr).digest()).digest().hex()
669e533b3f7fd1b165e64c197717506453b927a39cf1751262c31f8fd3cbcd26
v) append these 4 bytes to the output of step iii) above
0024f98038e995ee03c4178bccaff1652223eba473669e533b
vi) convert this to base58 encoding to get the address
>>> import base58
>>> rrrrr = “0024f98038e995ee03c4178bccaff1652223eba473669e533b”
>>> rrrrrr=bytes.fromhex(rrrrr)
>>> base58.b58encode(rrrr)
14NWDXkQwcGN1Pd9fboL8npVynD5SfyJAE
How do we pick a point for our address?
CONCEPT: Public Key Cryptography
The point on the elliptic curve is the public key anyone can use to make payments to (for example p2pk transactions in early bitcoin). The above address works in the same way as the public key but it is easier to use and more secure* (for example p2pkh transactions that came a bit later in bitcoin)
To receive bitcoins you don’t select a the public key, instead you select the private key and generate a public key from the private key.
Once you have selected a private key (random integer between 1 and 2^256) you generate a public key through scalar multiplication of the private key with a specific point G (the generator point) on the elliptic curve as defined by secp256k1’s definition. This generates a new point (the public key) on the curve from which you create your address as above.
Given a public key, they only way to know the private key is to check every possible private key (number between 1 and 2^256), which takes an impossibly long time. This is what secures bitcoin (CONCEPT: Elliptic curve cryptography)
The most important requirement for a private key is that is is random over the whole set of possible keys. Then if someone does try to search the entire key space they will not be able to spend your bitcoins because it would just take too long.
G=(0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798, 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8)
CONCEPT: Random numbers
Random number generation is a bit tricky for computers and humans to do. The two main issues are that random number generators on computers are often deterministic (predictable given seed values), or contain hidden patterns.
Good of private key generators are:
1. bitaddress.org – this takes various sources of entropy such as time, screen size, and mouse position as you wiggle it around and generates a private key using that
2. openssl – uses /dev/urandom in unix or CryptGenRandom() on Windows. These use system events such as packet times, process id’s etc as entropy and are generally well tested as unpredictable
e.g. (there’s probably a better way to do this but it worked on windows so i transferred it to mac)
i) mac$ openssl ecparam -genkey -name secp256k1 -out /var/tmp/delete_me -outform PEM
ii) mac$ openssl ec -inform PEM -in /var/tmp/delete_me -text -out /var/tmp/delete_me2
read EC key
writing EC key
iii) Private-Key: (256 bit)
priv:
26:db:4e:0b:f4:fa:35:db:7b:16:37:5f:3a:bb:c4:
e9:f0:30:de:85:b0:7b:6f:a2:cd:7e:32:a7:02:a2:
c4:16
pub:
04:4e:66:89:9a:b2:05:6e:6e:4d:bc:60:2f:e4:e7:
c0:7a:9c:35:35:f0:c3:0d:f1:c9:b1:08:01:9d:8d:
5e:43:fc:03:22:21:0e:ba:f6:64:b3:f2:ce:7c:8e:
8b:6c:e2:d3:22:8e:d1:ec:1d:de:65:24:03:e3:77:
2d:9b:b3:3d:0a
ASN1 OID: secp256k1
—–BEGIN EC PRIVATE KEY—–
MHQCAQEEICbbTgv0+jXbexY3Xzq7xOnwMN6FsHtvos1+MqcCosQWoAcGBSuBBAAK
oUQDQgAETmaJmrIFbm5NvGAv5OfAepw1NfDDDfHJsQgBnY1eQ/wDIiEOuvZks/LO
fI6LbOLTIo7R7B3eZSQD43ctm7M9Cg==
—–END EC PRIVATE KEY—–
iv) the bit after priv: is the private key in hex, and the bit after pub: is the public key point on the graph. Notice that it starts with 04 as the prefix to show it is sec uncompressed format
Some bad examples to generate private key (including the above public key address):
1. Brain wallets – these take a string of text and hash it to create a private key.
For example the private key for the above address is the hash of “bitcoin is awesome” (sha256(“bitcoin is awesome”)=0x23d4a09295be678b21a5f1dceae1f634a69c1b41775f680ebf8165266471401b which is the private key)
2. Insecure random number generators – using the java class SecureRandom to generate random numbers for private keys https://www.theregister.co.uk/2013/08/12/android_bug_batters_bitcoin_wallets/
Further questions:
1. How many addresses are there?
2. How the blockchain works?
3. What are transactions?
4. How are bitcoins created?
5. Given a private key how do you generate public key/address?
Resources: https://www.amazon.co.uk/Programming-Bitcoin-Learn-Program-Scratch/dp/1492031496
https://www.certicom.com/content/certicom/en/ecc-tutorial.html
https://en.bitcoin.it/wiki/Secp256k1
https://en.bitcoin.it/w/images/en/9/9b/PubKeyToAddr.png
https://www.theregister.co.uk/2013/08/12/android_bug_batters_bitcoin_wallets/