In this tutorial you will learn how to create a bitcoin address from coin flips. You can do the whole tutorial either offline or online. You can take either the end-user approach (easy) or the programmers / mathematicians approach (HARD! fun fun fun!).
End-user approach (the non technical approach)
Step 1: Flip a coin 256 times.
Write a one (1) on heads and a zero (0) on tails. An example result:
1
|
0101111110100010001011110100000101101111010...
|
Step 2: Convert it to a bitcoin private key.
Open the page https://brainwallet.github.io/#converter paste the numbers from above. Press Source Encoding: Bin, Convert To: Base58Check. Copy the result, its your private key.
Step 3: Import bitcoin private key
Import the bitcoin private key in your wallet. Please see your wallet homepage to import a private key. If you use bitcoind use:
1
|
./bitcoind importprivkey "5yourveryveryveryverylongprivatekeystring" "my-new-key"
|
And That’s how it’s done! If you like my tutorial, please share it with the buttons on the bottom of this post.
Programmers & Mathematicians approach
Step 1: Flip a coin 256 times
A bitcoin private key is a very large number. Every number can be represented in base 2 (binary) number. Get a coin and label one side (1 or positive) and one side (0 or negative). Flip the coin 256 times. The results could is a 256 bit sequence such as the one below (groups of4 for readability):
1
2
3
4
5
6
7
8
|
0101 1111 1010 0010 0010 1111 0100 0001
0110 1111 0101 0000 0001 1110 1101 1111
0010 1101 0101 1111 1010 0010 0010 1111
1101 1111 0010 1101 1111 0010 1101 1111
0010 1101 1111 0010 1101 1111 1101 1111
0110 1111 1101 0000 0001 1110 1101 1111
1010 1101 0101 1111 1010 0010 0010 1111
0110 1111 0101 0100 0001 1110 1101 1111
|
Step 2: Convert to decimal
Convert this huge binary number to decimal. In our case its the number 43256275986101861753551728768377656999160759540966415653480512874123449605855.
1
2
3
4
5
|
$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:38)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> int('YOUR BINARY NUMBER HERE',2)
|
Example run:
1
2
3
4
5
6
|
$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:38)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> int('0101111110100010001011110100000101101111010100000001111011011111001011010101111110100010001011111101111100101101111100101101111100101101111100101101111111011111011011111101000000011110110111111010110101011111101000100010111101101111010101000001111011011111',2)
43256275986101861753551728768377656999160759540966415653480512874123449605855L
|
By hand? Convert from base2 to base10. every place is in a binary number is 2^n if you want to do it by hand (from right to left). See the binary number system.
Step 3: Convert from decimal to base58
Copy the Base58 converter script I wrote and execute it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
# Base58 converter from talkera.org
# Convert Integer to Base58 and Base58 to Integer.
import os
import sys
import string
b58_digits = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
# this function from Armory, use for testing.
def base58str_to_int(b58str):
n = 0
for s in b58str:
n *= 58
digit = b58_digits.index(s)
n += digit
return n
# this function we've created
def int_to_base58str(int):
base58str = ""
while int > 0:
base58str += b58_digits[ int % 58 ]
int = int / 58;
base58str = base58str[::-1]
return base58str
# test values
#original = '7SKAkhb7meQtNhtC1wwyhdt5e3SFHdBjPZiEiLYniq6e'
#value = base58str_to_int(original)
#print int_to_base58str(value)
#print original
value = int(raw_input("Enter your large number: "))
print int_to_base58str(value)
|
Example run:
1
2
3
|
$ python basetest.py
Enter your large number: 43256275986101861753551728768377656999160759540966415653480512874123449605855
7SKAkhb7meQtNhtC1wwyhdt5e3SFHdBjPZiEiLYniq6e
|
By hand? To convert to base58 from base10 you need to divide the decimal number by 58. Save the modulo of each division and use this table to write the elements:
Finally, reverse the string. Let us take an example, the decimal number 591438166.
1
2
3
4
5
|
591438166% 58 = 44
10197209% 58 = 55
175813% 58 = 15
3031% 58 = 15
52% 58 = 52
|
We then look for each value in the table above. 44 = m, 55 = x, 15 = G, 15 = G, 52 = u. That makes mxGGU. We reverse the string and end up with uGGxm. Be careful with uppercase and lowercase.
Wait! We are not there yet. Now that you know how Base54 encoding works you need to convert it to the appropriate WIF (Wallet Import Format).
Step 4: Convert to WIF (Wallet Import Format)
Convert the decimal you found in step 2 to hexadecimal. “43256275986101861753551728768377656999160759540966415653480512874123449605855” becomes
“5fa22f416f501edf2d5fa22fdf2df2df2df2dfdf6fd01edfad5fa22f6f541edf”.
The steps to convert to WIF are (We have taken the values from the example). Don’t worry, just use my code below:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
1 - Take a private key
2 - Add a 0x80 byte in front of it for mainnet addresses or 0xef for testnet addresses. Also add a 0x01 byte at the end if the private key will correspond to a compressed public key
3 - Perform SHA-256 hash on the extended key
4 - Perform SHA-256 hash on result of SHA-256 hash
5 - Take the first 4 bytes of the second SHA-256 hash, this is the checksum
6 - Add the 4 checksum bytes from point 5 at the end of the extended key from point 2
7 - Convert the result from a byte string into a base58 string using Base58Check encoding. This is the Wallet Import Format
|
Use this code. Set the top value = “5fa22f416f501edf2d5fa22fdf2df2df2df2dfdf6fd01edfad5fa22f6f541edf” to your own value found in step 2 (in hexadecimal representation).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
# Base58 converter from talkera.org
# Convert Integer to Base58 and Base58 to Integer.
import os
import sys
import string
from hashlib import sha256
import binascii
b58_digits = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
# this function from Armory, use for testing.
def base58str_to_int(b58str):
n = 0
for s in b58str:
n *= 58
digit = b58_digits.index(s)
n += digit
return n
# this function we've created
def int_to_base58str(v):
base58str = ""
while v > 0:
base58str += b58_digits[ v % 58 ]
v = v / 58;
base58str = base58str[::-1]
return base58str
# 1. Take private key
#value = int(raw_input("Enter your large number: "))
#value = #"0C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D"
value = "5fa22f416f501edf2d5fa22fdf2df2df2df2dfdf6fd01edfad5fa22f6f541edf"
#print value
# 2. Add 80 in front of it
value = "80" + value
#print value
exp2 = value # Store extended key
# 3. Create SHA-256 on 2.
value = sha256(binascii.unhexlify(value)).hexdigest()
#print str(value)
# 4. Create SHA-256 on SHA-256.
value = sha256(binascii.unhexlify(value)).hexdigest()
#print str(value)
# 5. Take the first 4 bytes of the second SHA-256 hash
checksum = value[:8]
#print checksum
# 6. Add the 4 checksum bytes from point 5 at the end of the extended key from point 2
result = str(exp2) + str(checksum)
#print result
# 7. base58 encode
print "PRIVATE KEY = " + int_to_base58str(long(result,16))
|
Example run:
1
2
|
$ python base3.py
PRIVATE KEY = 5JYQQqSzTum7KjRvYUun69LKu5KwLkgYkLncC2rpRBj2i3kDbCm
|
Step 4: Import the private key (base58 string) in your wallet
Import the bitcoin private key in your wallet. Please see your wallet homepage to import a private key. If you use bitcoind use:
1
|
./bitcoind importprivkey "5yourveryveryveryverylongprivatekeystring" "my-new-key"
|
And That’s how it’s done! If you like my tutorial, please share it with the buttons on the bottom of this post.
Related work
https://bitcointalk.org/index.php?topic=944596.0
https://bitcointalk.org/index.php?topic=29140.0
https://bitcointalk.org/index.php?topic=129779.0
https://en.bitcoin.it/wiki/Base58Check_encoding
https://en.bitcoin.it/wiki/Wallet_import_format