'How can I build a bitcoin wallet?
I am going to work on a project in which we want to build a bitcoin wallet, like for example mycelium, coinbase etc, but I have no knowledge of which apis we should use to connect directly to the bitcoin blockchain 1could you give me recommendations for documentation on this. Thanks
Solution 1:[1]
Below is the step-by-step guide to create a bitcoin address via the Bash command line on Linux.
Warning! See Edit #1 at the end.
This way you will understand how you can create an app (wallet) that generates Bitcoin addresses.
Wallet and public address are different things: a wallet is an application that creates and stores private keys and makes the public key available as the crypto address where the coins will be received.
Note that the steps are incremental. The next step always has the copy of the previous step.
# a1) Prerequisite of installed applications.
apt-get install -y openssl base58 grep xxd
# a2) Choose a password.
PASSWORD="my-difficult-passphrase"
# a3) Hash SHA256 over the password.
# Don't use echo because it adds \n to the end.
PASSWORD="my-difficult-passphrase"; printf $PASSWORD | openssl sha256
# a4) Keep only the hex output. We're going to use this often.
PASSWORD="my-difficult-passphrase"; printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}"
# a5) Add two magic numbers...
# - at the beginning: 302e0201010420
# - and at the end: a00706052b8104000a
# They relate to secp256k1 refers to the parameters of the elliptic curve used in Bitcoin's cryptography.
PASSWORD="my-difficult-passphrase"; printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a"
# a6) Get the bytes of this hex.
PASSWORD="my-difficult-passphrase"; printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps
# a7) Generate the Elliptic-curve key pair.
PASSWORD="my-difficult-passphrase"; openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps)
# At this point we have the key pair.
# b) With the public key we will make the bitcoin address.
# c) The private key is converted to WIF format (Wallet Import Format)
# b1) Extract the hex value from the public key.
PASSWORD="my-difficult-passphrase"; openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n'
# b2) Convert to bytes.
PASSWORD="my-difficult-passphrase"; openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps
# b3) Hash SHA256.
PASSWORD="my-difficult-passphrase"; openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps | openssl sha256
# b4) Keep only the hex output.
PASSWORD="my-difficult-passphrase"; openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}"
# b5) Convert to bytes.
PASSWORD="my-difficult-passphrase"; openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps
# b6) Hash RIPEMD-160.
PASSWORD="my-difficult-passphrase"; openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl ripemd160
# b7) Keep only the hex output.
PASSWORD="my-difficult-passphrase"; openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl ripemd160 | grep -o "[0-9a-f]\{40\}"
# b8) We prefix the hex with "00".
# Bitcoin P2PKH addresses begin with the version byte value 0x00.
PASSWORD="my-difficult-passphrase"; printf "00$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl ripemd160 | grep -o "[0-9a-f]\{40\}")"
# Now get a checksum by passing the SHA256 hash twice in the hex bytes.
# b9) Checksum loop 1. Convert to bytes.
PASSWORD="my-difficult-passphrase"; printf "00$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl ripemd160 | grep -o "[0-9a-f]\{40\}")" | xxd -r -ps
# b10) Checksum loop 1. Hash SHA256.
PASSWORD="my-difficult-passphrase"; printf "00$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl ripemd160 | grep -o "[0-9a-f]\{40\}")" | xxd -r -ps | openssl sha256
# b11) Checksum loop 1. Keep only the hex output.
PASSWORD="my-difficult-passphrase"; printf "00$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl ripemd160 | grep -o "[0-9a-f]\{40\}")" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}"
# b12) Checksum loop 2. Convert to bytes.
PASSWORD="my-difficult-passphrase"; printf "00$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl ripemd160 | grep -o "[0-9a-f]\{40\}")" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps
# b13) Checksum loop 2. Hash SHA256.
PASSWORD="my-difficult-passphrase"; printf "00$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl ripemd160 | grep -o "[0-9a-f]\{40\}")" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl sha256
# b14) Checksum loop 2. Keep only the hex output.
PASSWORD="my-difficult-passphrase"; printf "00$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl ripemd160 | grep -o "[0-9a-f]\{40\}")" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}"
# b15) Get the first 4 bytes (or 8 chars) of the checksum.
PASSWORD="my-difficult-passphrase"; printf "00$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl ripemd160 | grep -o "[0-9a-f]\{40\}")" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | grep -o "^[0-9a-f]\{8\}"
# Checksum completed here.
# b16) Add the checksum to the end of the
# hex prefixed with "00" in step b8.
PASSWORD="my-difficult-passphrase"; printf "$(printf "00$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl ripemd160 | grep -o "[0-9a-f]\{40\}")")$(printf "00$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl ripemd160 | grep -o "[0-9a-f]\{40\}")" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | grep -o "^[0-9a-f]\{8\}")"
# b17) Convert to bytes.
PASSWORD="my-difficult-passphrase"; printf "$(printf "00$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl ripemd160 | grep -o "[0-9a-f]\{40\}")")$(printf "00$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl ripemd160 | grep -o "[0-9a-f]\{40\}")" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | grep -o "^[0-9a-f]\{8\}")" | xxd -r -ps
# b18) Encode with Base58.
PASSWORD="my-difficult-passphrase"; printf "$(printf "00$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl ripemd160 | grep -o "[0-9a-f]\{40\}")")$(printf "00$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | grep -o "[0-9a-f]" | tr -d '\n' | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl ripemd160 | grep -o "[0-9a-f]\{40\}")" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | grep -o "^[0-9a-f]\{8\}")" | xxd -r -ps | base58
# Here the bitcoin address ends
# c1) Extract the hex value from the private key.
PASSWORD="my-difficult-passphrase"; openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -10 | head -3 | grep -o "[0-9a-f]" | tr -d '\n'
# c2) Ensures length of 32 bytes (or 64 chars) by padding with zeros.
PASSWORD="my-difficult-passphrase"; printf "0000000000000000000000000000000000000000000000000000000000000000$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -10 | head -3 | grep -o "[0-9a-f]" | tr -d '\n')" | grep -o "[0-9a-f]\{64\}$"
# c3) We prefix the hex with "80".
# The magic number 0x80 signals the version of the private key.
PASSWORD="my-difficult-passphrase"; printf "80$(printf "0000000000000000000000000000000000000000000000000000000000000000$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -10 | head -3 | grep -o "[0-9a-f]" | tr -d '\n')" | grep -o "[0-9a-f]\{64\}$")"
# Again: Now get a checksum by passing the SHA256 hash twice in the hex bytes.
# c4) Checksum loop 1. Convert to bytes.
PASSWORD="my-difficult-passphrase"; printf "80$(printf "0000000000000000000000000000000000000000000000000000000000000000$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -10 | head -3 | grep -o "[0-9a-f]" | tr -d '\n')" | grep -o "[0-9a-f]\{64\}$")" | xxd -r -ps
# c5) Checksum loop 1. Hash SHA256.
PASSWORD="my-difficult-passphrase"; printf "80$(printf "0000000000000000000000000000000000000000000000000000000000000000$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -10 | head -3 | grep -o "[0-9a-f]" | tr -d '\n')" | grep -o "[0-9a-f]\{64\}$")" | xxd -r -ps | openssl sha256
# c6) Checksum loop 1. Keep only the hex output.
PASSWORD="my-difficult-passphrase"; printf "80$(printf "0000000000000000000000000000000000000000000000000000000000000000$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -10 | head -3 | grep -o "[0-9a-f]" | tr -d '\n')" | grep -o "[0-9a-f]\{64\}$")" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}"
# c7) Checksum loop 2. Convert to bytes.
PASSWORD="my-difficult-passphrase"; printf "80$(printf "0000000000000000000000000000000000000000000000000000000000000000$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -10 | head -3 | grep -o "[0-9a-f]" | tr -d '\n')" | grep -o "[0-9a-f]\{64\}$")" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps
# c8) Checksum loop 2. Hash SHA256.
PASSWORD="my-difficult-passphrase"; printf "80$(printf "0000000000000000000000000000000000000000000000000000000000000000$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -10 | head -3 | grep -o "[0-9a-f]" | tr -d '\n')" | grep -o "[0-9a-f]\{64\}$")" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl sha256
# c9) Checksum loop 2. Keep only the hex output.
PASSWORD="my-difficult-passphrase"; printf "80$(printf "0000000000000000000000000000000000000000000000000000000000000000$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -10 | head -3 | grep -o "[0-9a-f]" | tr -d '\n')" | grep -o "[0-9a-f]\{64\}$")" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}"
# c10) Get the first 4 bytes (or 8 chars) of the checksum.
PASSWORD="my-difficult-passphrase"; printf "80$(printf "0000000000000000000000000000000000000000000000000000000000000000$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -10 | head -3 | grep -o "[0-9a-f]" | tr -d '\n')" | grep -o "[0-9a-f]\{64\}$")" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | grep -o "^[0-9a-f]\{8\}"
# Checksum completed here.
# c11) Add the checksum to the end of the
# hex prefixed with "80" in step c3.
PASSWORD="my-difficult-passphrase"; printf "$(printf "80$(printf "0000000000000000000000000000000000000000000000000000000000000000$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -10 | head -3 | grep -o "[0-9a-f]" | tr -d '\n')" | grep -o "[0-9a-f]\{64\}$")")$(printf "80$(printf "0000000000000000000000000000000000000000000000000000000000000000$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -10 | head -3 | grep -o "[0-9a-f]" | tr -d '\n')" | grep -o "[0-9a-f]\{64\}$")" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | grep -o "^[0-9a-f]\{8\}")"
# c12) Convert to bytes.
PASSWORD="my-difficult-passphrase"; printf "$(printf "80$(printf "0000000000000000000000000000000000000000000000000000000000000000$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -10 | head -3 | grep -o "[0-9a-f]" | tr -d '\n')" | grep -o "[0-9a-f]\{64\}$")")$(printf "80$(printf "0000000000000000000000000000000000000000000000000000000000000000$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -10 | head -3 | grep -o "[0-9a-f]" | tr -d '\n')" | grep -o "[0-9a-f]\{64\}$")" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | grep -o "^[0-9a-f]\{8\}")" | xxd -r -ps
# c13) Encode with Base58.
PASSWORD="my-difficult-passphrase"; printf "$(printf "80$(printf "0000000000000000000000000000000000000000000000000000000000000000$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -10 | head -3 | grep -o "[0-9a-f]" | tr -d '\n')" | grep -o "[0-9a-f]\{64\}$")")$(printf "80$(printf "0000000000000000000000000000000000000000000000000000000000000000$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}")a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -10 | head -3 | grep -o "[0-9a-f]" | tr -d '\n')" | grep -o "[0-9a-f]\{64\}$")" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | xxd -r -ps | openssl sha256 | grep -o "[0-9a-f]\{64\}" | grep -o "^[0-9a-f]\{8\}")" | xxd -r -ps | base58
# Here the private key as WIF ends
Below is the same sequence of steps in one line commands for Bash:
PASSWORD="my-difficult-passphrase"; printf "\nBitcoin Wallet\n\nPassword:\n$PASSWORD\n\nPrivate Key:\n$(printf "0000000000000000000000000000000000000000000000000000000000000000$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf "$PASSWORD" | sha256sum | sed 's/[^a-z0-9]//g')a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -10 | head -3 | sed 's/[ :]//g' | tr -d '\n')" | sed 's/.*\(.\{64\}$\)/\1/')\n\nPrivate Key, WIF:\n$(printf "$(printf "80$(printf "0000000000000000000000000000000000000000000000000000000000000000$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf $PASSWORD | openssl sha256 | sed 's/^.*\s//g')a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -10 | head -3 | sed 's/[ :]//g' | tr -d '\n')" | sed 's/.*\(.\{64\}$\)/\1/')")$(printf "80$(printf "0000000000000000000000000000000000000000000000000000000000000000$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf "$PASSWORD" | openssl sha256 | sed 's/^.*\s//g')a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -10 | head -3 | sed 's/[ :]//g' | tr -d '\n')" | sed 's/.*\(.\{64\}$\)/\1/')" | xxd -r -ps | openssl sha256 | sed 's/^.*\s//g' | awk 'ORS=" "' | sed 's/\W//g' | xxd -r -ps | openssl sha256 | sed 's/^.*\s//g' | awk 'ORS=" "' | sed 's/\W//g' | sed 's/\(.\{8\}\).*/\1/')" | xxd -r -ps | base58)\n\nPublic Key:\n$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf "$PASSWORD" | sha256sum | sed 's/[^a-z0-9]//g')a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | sed 's/[ :]//g' | tr -d '\n')\n\nPublic Key, Wallet:\n$(printf "$(printf "00$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf "$PASSWORD" | openssl sha256 | sed 's/^.*\s//g')a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | sed 's/[ :]//g' | tr -d '\n' | xxd -r -ps | openssl sha256 | sed 's/^.*\s//g' | awk 'ORS=" "' | sed 's/\W//g' | xxd -r -ps | openssl ripemd160 | sed 's/.*\s//' | awk 'ORS=" "' | sed 's/\W//g')")$(printf "00$(openssl ec -inform DER -text -noout -in <(printf "302e0201010420$(printf "$PASSWORD" | openssl sha256 | sed 's/^.*\s//g')a00706052b8104000a" | xxd -r -ps) 2>/dev/null | tail -6 | head -5 | sed 's/[ :]//g' | tr -d '\n' | xxd -r -ps | openssl sha256 | sed 's/^.*\s//g' | awk 'ORS=" "' | sed 's/\W//g' | xxd -r -ps | openssl ripemd160 | sed 's/.*\s//' | awk 'ORS=" "' | sed 's/\W//g')" | xxd -r -ps | openssl sha256 | sed 's/^.*\s//g' | awk 'ORS=" "' | sed 's/\W//g' | xxd -r -ps | openssl sha256 | sed 's/^.*\s//g' | awk 'ORS=" "' | sed 's/\W//g' | sed 's/\(.\{8\}\).*/\1/')" | xxd -r -ps | base58)\n\n"
Now the same one line command for PowerShell (perhaps for Windows).
$password="my-difficult-passphrase"; $tempFile="$env:temp/btcaddress.tmp"; [System.IO.File]::WriteAllText($tempFile, $password); $passwordSha256=$(openssl sha256 $tempFile | Select-String "[0-9a-f]{64}").Matches[0].Value; $passwordSha256Secp256k1="302e0201010420${passwordSha256}a00706052b8104000a"; [System.IO.File]::WriteAllBytes($tempFile, [System.Convert]::FromHexString($passwordSha256Secp256k1)); $keys=$($(openssl ec -inform DER -text -noout -in $tempFile | Select-String "(?<=^\s+)[0-9a-f:]+").Matches | Select-Object -Property Value | ForEach-Object -Process {$_.Value.Replace(":", "")}); $keyPrivate=$keys[0]+$keys[1]+$keys[2]; $keyPublic=$keys[3]+$keys[4]+$keys[5]+$keys[6]+$keys[7]; [System.IO.File]::WriteAllBytes($tempFile, [System.Convert]::FromHexString($keyPublic)); $keyPublicSha256=$(openssl sha256 $tempFile | Select-String "[0-9a-f]{64}").Matches[0].Value; [System.IO.File]::WriteAllBytes($tempFile, [System.Convert]::FromHexString($keyPublicSha256)); $keyPublicSha256Ripemd160=$(openssl ripemd160 $tempFile | Select-String "[0-9a-f]{40}").Matches[0].Value; $keyPublicSha256Ripemd160Prefixed="00"+$keyPublicSha256Ripemd160; [System.IO.File]::WriteAllBytes($tempFile, [System.Convert]::FromHexString($keyPublicSha256Ripemd160Prefixed)); $keyPublicSha256Ripemd160Checksum=$(openssl sha256 $tempFile | Select-String "[0-9a-f]{64}").Matches[0].Value; [System.IO.File]::WriteAllBytes($tempFile, [System.Convert]::FromHexString($keyPublicSha256Ripemd160Checksum)); $keyPublicSha256Ripemd160Checksum=$(openssl sha256 $tempFile | Select-String "[0-9a-f]{64}").Matches[0].Value.Substring(0, 8); $bitcoinKeyPublic="$keyPublicSha256Ripemd160Prefixed$keyPublicSha256Ripemd160Checksum"; $keyPrivatePrefixed="80"+$keyPrivate.PadLeft(64, '0'); [System.IO.File]::WriteAllBytes($tempFile, [System.Convert]::FromHexString($keyPrivatePrefixed)); $keyPrivateChecksum=$(openssl sha256 $tempFile | Select-String "[0-9a-f]{64}").Matches[0].Value; [System.IO.File]::WriteAllBytes($tempFile, [System.Convert]::FromHexString($keyPrivateChecksum)); $keyPrivateChecksum=$(openssl sha256 $tempFile | Select-String "[0-9a-f]{64}").Matches[0].Value.Substring(0, 8); $bitcoinKeyPrivate="$keyPrivatePrefixed$keyPrivateChecksum"; function Base58 { param ([parameter(valuefrompipeline=$true)] [string]$1) $i=[bigint]::Parse($1,"AllowHexSpecifier"); $chars=@(); $index =@('1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','J','K','L','M','N','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','m','n','o','p','q','r','s','t','u','v','w','x','y','z'); if (($1).length % 2 -ne 0 -OR $i -lt 0) { $1="0$1"; $i=[bigint]::Parse($1, "AllowHexSpecifier"); } while($i -gt 0) { $m=([bigInt]$i % 58); $i=([bigInt]$i / 58); $chars+=$index[$m]; } [array]::reverse($chars); $i=$chars -join (''); $1 -split "(..)" | ForEach-Object { if ($_ -match "00") { $i=("1"+$i); } else { return; } }; $chars=@(); $chars.clear(); $index=@(); $index.clear(); return $i; }; $bitcoinKeyPrivateBase58=Base58($bitcoinKeyPrivate); $bitcoinKeyPublicBase58=Base58($bitcoinKeyPublic); [System.IO.File]::Delete($tempFile); Write-Output "Bitcoin Wallet`n`nPassword:`n$password`n`nPrivate Key:`n$keyPrivate`n`nPrivate Key, WIF:`n$bitcoinKeyPrivateBase58`n`nPublic Key:`n$keyPublic`n`nPublic Key, Wallet:`n$bitcoinKeyPublicBase58`n`n"
For the above commands just copy and paste into the terminal.
You can check the generated data on other sites. Use the same password in Brain Wallet mode and uncheck "Compressed address".
BitAddress.org
Coinb.in
Edit #1
Between steps a4 and a5 we have a very large number as a result. But not all numbers in the 2^256
range are on the mathematical secp256k1 elliptic curve used for finding a matching public key. The range, is actually from 0
to 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
(in decimal: 115792089237316195423570985008687907852837564279074904382605163141518161494337
), as defined in the SEC2 standard. Read more about DOES THAT MEAN THERE ARE 2^256 POSSIBLE PRIVATE KEYS?.
Check if the hash is less than this value. The following command displays the hash value in decimal numeric format:
PASSWORD="my-difficult-passphrase"; echo "ibase=16; $(printf $PASSWORD | openssl sha256 | grep -o "[0-9a-f]\{64\}" | tr a-z A-Z)" | bc | awk 'ORS=" "' | sed 's/\W//g'
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |