Never Use a Brain Wallet
Among many reasons why people find it hard to use cryptocurrency there’s a simple one – memorising the private key is too hard. So, people invented brain wallet, which turns a string of words into a private key and thus wallet.
It’s genius in that now a user needs only to memorise whatever he or she used to create the wallet. You can turn your name, phone number, DoB, favourite quote, lover’s home address, …, literally anything into a cryptocurrency wallet. However, this also means that if someone else successfully guessed the passphrase you used, they can sweep all the coins you have!
Python brain wallet for Bitcoin
After a little bit of research, I’ve put together a simple brain wallet Python script that turns any input string to a legal Bitcoin private key and its address.
import codecs
import hashlib
import ecdsa
class BrainWallet:
@staticmethod
def generate_address_from_passphrase(passphrase):
= str(hashlib.sha256(
private_key 'utf-8')).hexdigest())
passphrase.encode(= BrainWallet.generate_address_from_private_key(private_key)
address return private_key, address
@staticmethod
def generate_address_from_private_key(private_key):
= BrainWallet.__private_to_public(private_key)
public_key = BrainWallet.__public_to_address(public_key)
address return address
@staticmethod
def __private_to_public(private_key):
= codecs.decode(private_key, 'hex')
private_key_bytes # Get ECDSA public key
= ecdsa.SigningKey.from_string(
key =ecdsa.SECP256k1).verifying_key
private_key_bytes, curve= key.to_string()
key_bytes = codecs.encode(key_bytes, 'hex')
key_hex # Add bitcoin byte
= b'04'
bitcoin_byte = bitcoin_byte + key_hex
public_key return public_key
@staticmethod
def __public_to_address(public_key):
= codecs.decode(public_key, 'hex')
public_key_bytes # Run SHA256 for the public key
= hashlib.sha256(public_key_bytes)
sha256_bpk = sha256_bpk.digest()
sha256_bpk_digest # Run ripemd160 for the SHA256
= hashlib.new('ripemd160')
ripemd160_bpk
ripemd160_bpk.update(sha256_bpk_digest)= ripemd160_bpk.digest()
ripemd160_bpk_digest = codecs.encode(ripemd160_bpk_digest, 'hex')
ripemd160_bpk_hex # Add network byte
= b'00'
network_byte = network_byte + ripemd160_bpk_hex
network_bitcoin_public_key = codecs.decode(
network_bitcoin_public_key_bytes 'hex')
network_bitcoin_public_key, # Double SHA256 to get checksum
= hashlib.sha256(network_bitcoin_public_key_bytes)
sha256_nbpk = sha256_nbpk.digest()
sha256_nbpk_digest = hashlib.sha256(sha256_nbpk_digest)
sha256_2_nbpk = sha256_2_nbpk.digest()
sha256_2_nbpk_digest = codecs.encode(sha256_2_nbpk_digest, 'hex')
sha256_2_hex = sha256_2_hex[:8]
checksum # Concatenate public key and checksum to get the address
= (network_bitcoin_public_key + checksum).decode('utf-8')
address_hex = BrainWallet.base58(address_hex)
wallet return wallet
@staticmethod
def base58(address_hex):
= '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
alphabet = ''
b58_string # Get the number of leading zeros and convert hex to decimal
= len(address_hex) - len(address_hex.lstrip('0'))
leading_zeros # Convert hex to decimal
= int(address_hex, 16)
address_int # Append digits to the start of string
while address_int > 0:
= address_int % 58
digit = alphabet[digit]
digit_char = digit_char + b58_string
b58_string //= 58
address_int # Add '1' for each 2 leading zeros
= leading_zeros // 2
ones for one in range(ones):
= '1' + b58_string
b58_string return b58_string
Easily “cracking” a wallet
Let me show you some really easy-to-guess passphrases and their associated private keys and addresses. As an example, the code below uses “password” as the input passphrase and derives the private key and address from it.
= 'password'
passphrase = BrainWallet()
wallet = wallet.generate_address_from_passphrase(passphrase)
private_key, address print(f'passphrase: {passphrase}')
print(f'private key: {private_key}')
print(f'address: {address}')
The output is:
passphrase: password5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
private key: 16ga2uqnF1NqpAuQeeg7sTCAdtDUwDyJav address:
As at May 22, 2019, this address has 45,014 transactions with a total of 0.3563 BTC (of course the balance is zero)! You can check its current balance at blockchain.com. Also, congratulations, you are now one of the many owners of this address/wallet. So next time you observe some coins transfered to it, you’ll be able to use it as well (though I don’t suggest you to do so)!
Some other “cracked” wallets
I explored a little bit more and it’s surprising to find out how easy it is to crack a wallet this way. Below is a table of some passphrases and their associated keys and addresses.
Passphrase | Private Key | Address | Used |
---|---|---|---|
satoshi | da2876b3eb31edb4436fa4650673fc6f01f90de2f1793c4ec332b2387b09726f | 1ADJqstUMBB5zFquWg19UqZ7Zc6ePCpzLE | True |
bitcoin | 6b88c087247aa2f07ee1c5956b8e1a9f4c7f892a70e324f1bb3d161e05ca107b | 1E984zyYbNmeuumzEdqT8VSL8QGJi3byAD | True |
hello world | b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9 | 1CS8g7nwaxPPprb4vqcTVdLCuCRirsbsMb | True |
testing | cf80cd8aed482d5d1527d7dc72fceff84e6326592848447d2dc0b0e87dfc9a90 | 1JdDsbYYRSpsTnBVgenruULVeUjt5z6WnR | True |
god | 5723360ef11043a879520412e9ad897e0ebcb99cc820ec363bfecc9d751a1a99 | 1KxmSmcMTmPvU1qSLYpJLrqnSzBoQ53NXN | True |
terminator | aa802f654e3ae7aaa1b73f8724056a05e2691accea8dd90057916080f84d7e93 | 18kvt3D6K1CG8MxGP6ke7q6vLU5NGpLZdR | True |
abc | ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad | 1NEwmNSC7w9nZeASngHCd43Bc5eC2FmXpn | True |
And a lot of swear words are used as well, but I’m just going to skip them.
Apart from the single world and short phrases, some people do use famous quotes. As an example, see this one from A Tale of Two Cities:
it was the best of times it was the worst of times
Its private key is af8da705bfd95621983e5cf4232ac1ca0c79b47122e3defd8a98fa9a4387d985
and its address is 17WenQJaYvqCNumebQU54TsixWtQ1GQ4ND. It has received 1 BTC in total but again the balance is zero, lol.
Concluding remark
Never use a brain wallet. Because if you can think of it, someone else might also be able to come up with same passphrase. But, if you are comfortable or absolutely sure that your passphrase is secret, feel free to use the script above and make yourself a wallet. 😏