Python code to manually create 12/24 worded seed and passphrase without trusting Bitcoin wallets.
Creating a Bitcoin wallets means generating long enough random numbers infeasible to guess by others and keeping it safe.
While creating a Bitcoin wallet in hardware wallets or Mobile wallet, it generates 12-24 words. Those 12-24 words are the part of private key for Bitcoin, and whoever knows that private keys can access the Bitcoin. Thus it is important to create that private key in safe environment. If you are crating a Bitcoin wallet akka seeds aka private key in a wallet, this is what goes under the hood:
Step 1 : Wallet creates a long enough random numbers.
Step 2 : A checksum is appended to this random number.
Step 3 : Resultant number is divided into chunks, each with the length of 11 bits and each chunk is mapped to a English word from the dictionary of 2¹¹ ~ 2048 words.
Here we will create those seed words manually with basic python code. Step 1 and 3 can be done with pen and pencil within few minutes. Step 2 requires computing SHA256 once which we can be done with pen and pencil in few hours but I wouldn’t recommend it as it is prone to error.
I have tried to simplify the python code for those who gets scared looking at classes and objects.
BIP30 explains how to generate seed words. You can find the original code implementation of BIP39 here https://github.com/trezor/python-mnemonic/blob/master/mnemonic/mnemonic.py
Warning: This code contains Bitcoin private key. Make sure you are running this code in secure machine.
Step 1: Generating entropy by flipping coins.
I am using python instead of pen and paper. We will need some libraries.
import hashlib # for SHA256 computation
import binascii # for conversion between Hexa and bytes
The mnemonic must encode entropy in a multiple of 32 bits. The allowed size of initial entropy is 128–256 bits. You should generate your own entropy by flipping a coin or throwing a dice. Notice that length of entropy I entered is 48 in hexa or 192 in binary which is a multiple of 32.
entropy = “c10ec20dc3cd9f652c7fac2f1230f7a3c828389a14392f05”
We need to make sure the length of entropy is following BIP39 standard.
data = entropy.strip() #cleaning of data
data = binascii.unhexlify(data)if len(data) not in [16, 20, 24, 28, 32]:
“Data length should be one of the following: [16, 20, 24, 28, 32], but it is not (%d).” % len(data)
Step 2: Generate checksum and append to end of entropy.
A checksum is generated by taking the first ENT/32 bits of its SHA256 hash. This checksum is appended to the end of the initial entropy. Purpose of appending checksum is to detect typos in the seed entered. It only helps to some extent depending upon the length of entropy.
h = hashlib.sha256(data).hexdigest()b = bin(int(binascii.hexlify(data),16))[2:].zfill(len(data)*8) + bin(int(h,16))[2:].zfill(256)[: len(data)* 8//32]
Next, these concatenated bits are split into groups of 11 bits, each encoding a number from 0–2047, serving as an index into a word list. Finally, we convert these numbers into words and use the joined words as a mnemonic sentence.
with open("wordlist/english.txt", "r") as f:
wordlist = [w.strip() for w in f.readlines()]
Step 3: Mapping to word list
I am assuming that 2048 dictionary of words specified in BIP39 is in file wordlist/english.txt
You can find word list here https://github.com/trezor/python-mnemonic/tree/master/mnemonic
seed = 
for i in range(len(b)//11):
indx = int(b[11*i:11*(i+1)],2)
For our chosen entropy, seed words should be [‘scissors’, ‘invite’, ‘lock’, ‘maple’, ‘supreme’, ‘raw’, ‘rapid’, ‘void’, ‘congress’, ‘muscle’, ‘digital’, ‘elegant’, ‘little’, ‘brisk’, ‘hair’, ‘mango’, ‘congress’, ‘clump’]
Next article will be on how to generate Bitcoin address and private key for that address from these seeds.