Today I’m going to talk about bx.
bx (Bitcoin eXplorer) is a little command line tool that allows you to do, erm, bitcoin!, on the command line.
It’s a front-end for the underlying library, libbitcoin on which it’s built. Similar to openssl, bx is a ‘swiss army knife’ type command, offering many subcommands that can do different things. Combining these sub-commands through unix pipes, we can do many practical commands. Combine with bash, and you have even more power. Let’s dive in!
Here’s a bitcoin address:
As you may or may not know, a bitcoin address is a base58-check encoded representation of a public key hash. It’s generated by SHA256ing the public key, then RIPEMD160ing the result, to give a 160-bit hash, which is known as a “PKH” (Public Key Hash).
To turn this into a standard bitcoin address, a version byte (0x00) is prepended, then a 4-byte checksum (which is another double-SHA256, this time of the version byte concatenated with the RIPEMD160), is appended, giving a total of 165 bytes:
[Version Byte][160bit PubkeyHash][4-byte checksum]
This is then base58-check-encoded to give something which looks like the address above.
Let’s do the reverse. First let’s generate a random bitcoin private key:
[user@bitcoin libbitcoin-explorer]$ bx seed | bx ec-new 69bc69641bd3111e47d55c40b8f1e912577c78edabb1c8ca5d2907bff7a93097
So now have a private key (69bc69641bd3111e47d55c40b8f1e912577c78edabb1c8ca5d2907bff7a93097). Let’s convert that private key into a public key:
[user@bitcoin libbitcoin-explorer]$ echo 69bc69641bd3111e47d55c40b8f1e912577c78edabb1c8ca5d2907bff7a93097 | bx ec-to-public 0380864b7759a43923d2d0c99b142843fc306199a94995e55cb204d9a91fa09feb
This is our public key. There’s only one more step in converting it to a standard mainnet bitcoin address, and that’s the ec-to-address subcommand. But let’s do it 2 ways so we may better understand exactly what ec-to-address is doing. So first the easy way:
[user@bitcoin libbitcoin-explorer]$ echo 0380864b7759a43923d2d0c99b142843fc306199a94995e55cb204d9a91fa09feb | bx ec-to-address 1LmqvzD5KgNs1a8tcibuiNNM1MfZxLr5pw
So there’s our nice short bitcoin address which under no circumstances should you send any money to, unless you want to lose it! Ok now for the long way. First is our hashing step. This involves SHA256ing the public key (bitwise), SHA256ing the SHA256 from the previous step (bitwise), and finally RIPEMD160’ing the SHA256 from the previous step. Bitwise.
[user@bitcoin libbitcoin-explorer]$ echo 0380864b7759a43923d2d0c99b142843fc306199a94995e55cb204d9a91fa09feb | bx sha256 b02260cfb06dfafc55c4c38ace673ce0c902ec0de84fbc75a19adce6bfc9bf9c [user@bitcoin libbitcoin-explorer]$ echo b02260cfb06dfafc55c4c38ace673ce0c902ec0de84fbc75a19adce6bfc9bf9c | bx ripemd160 d8e5899f2589b7fa9df2513bf2366d2031f2d478
These steps can be combined into one line:
[user@bitcoin libbitcoin-explorer]$ echo 0380864b7759a43923d2d0c99b142843fc306199a94995e55cb204d9a91fa09feb | bx sha256 | bx ripemd160 d8e5899f2589b7fa9df2513bf2366d2031f2d478
Next we prepend our version byte (0x00), giving 21 bytes:
Then we double-SHA256 it:
[user@bitcoin libbitcoin-explorer]$ echo 00d8e5899f2589b7fa9df2513bf2366d2031f2d478 | bx sha256 | bx sha256 08c131a41c9ba6763e87c037f3eb9fa75b8f593750e8d070cd03cff71c07f02d
Next we take the first 4 bytes from this result (0x08c131a4), and append that to the [version byte|hash160] string, giving 25 bytes:
Finally, let’s base58-encode this and see what we get:
[user@bitcoin libbitcoin-explorer]$ echo 00d8e5899f2589b7fa9df2513bf2366d2031f2d47808c131a4 | bx base58-encode 1LmqvzD5KgNs1a8tcibuiNNM1MfZxLr5pw
Same address! Done the long way.