btctool v0.3.0 BtcTool View Source
Bitcoin utils related to Elliptic curve cryptography (ECC) algorithms used in bitcoin to create addresses or public keys from private keys, brainwallets, WIFs, etc.
Link to this section Summary
Types
Hash which includes WIF, private key and metadata
Wallet Import Format string ready to be imported into a wallet. It uses base58check characters. The raw private key can be extracted from this
Functions
Create Wallet Import Format (WIF) private key from raw private key. A raw private key can be presented by a binary of 32 bytes or in 64 hexadecimal characters (0-9a-fA-F)
Returns the raw private key from a Wallet Import Format (WIF) string. Including metadata from WIF telling:
compressed
: If when generating the public key, should use compressed format or uncompressed.network
: Where the private key should be used. In mainnet, or testnet
Link to this section Types
Hash which includes WIF, private key and metadata.
WIF string
Wallet Import Format string containing the private key. It also includes metadata with information extracted from the WIF string.
WIF will be a base58check string of 51 characters (408 bits) if user want to use uncompressed public keys in the bitcoin addresses, or 52 characters (416 bits) if wants to use compressed public keys.
Raw private key
Raw private key in binary format (512bits) and hexadecimal format (characters a-z0-9).
Available metadata
Metadata like network
or compressed
is deducted from the WIP
string:
network
. Which network (:mainnet
, or:testnet
) is intended to be used the private key.compressed
. States if when using private key to generate an address should use the compressed or uncompressed version of the public key. NOTE: Nowadays is normal to use the compressed version.
Wallet Import Format string ready to be imported into a wallet. It uses base58check characters. The raw private key can be extracted from this.
Examples:
- Uncompressed private key to be imported (51 characters in base58,
starts with
5
) E.g.:5HpneLQNKrcznVCQpzodYwAmZ4AoHeyjuRf9iAHAa498rP5kuWb
- Compressed private key to be imported (52 characters in base58,
starts with
K
orL
) E.g.:KwFvTne98E1t3mTNAr8pKx67eUzFJWdSNPqPSfxMEtrueW7PcQzL
Link to this section Functions
privkey_to_wif(<<_::512>> | <<_::256>>, [{atom(), any()}]) :: {:ok, privkey_result()} | {:error, atom()}
Create Wallet Import Format (WIF) private key from raw private key. A raw private key can be presented by a binary of 32 bytes or in 64 hexadecimal characters (0-9a-fA-F)
It assumes you want the compressed WIF version by default. That way you are signalling that the bitcoin address which should be used when imported into a wallet will be also compressed.
Options
compressed
- Generate a WIF which signals that a compressed public key should be used iftrue
. Default totrue
.network
- Specifies the network this private key intended to be used on. Can be:mainnet
or:testnet
. Default is:mainnet
.case
- Ensures the character case to accept when decoding. Valid values are::upper
,:lower
,:mixed
. Only useful when the raw private key is passed in hex format. If case is not satisfied will return an error. Default is:mixed
Examples
iex> hexprivkey = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
iex> privkey_to_wif(hexprivkey)
{:ok, %{
wif: "KwFvTne98E1t3mTNAr8pKx67eUzFJWdSNPqPSfxMEtrueW7PcQzL",
privkey_bin: <<1, 35, 69, 103, 137, 171, 205, 239, 1, 35, 69, 103, 137, 171, 205, 239, 1, 35, 69, 103, 137, 171, 205, 239, 1, 35, 69, 103, 137, 171, 205, 239>>,
privkey_hex: "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF",
compressed: true,
network: :mainnet
}}
iex> binprivkey = hexprivkey |> Base.decode16!()
<<1, 35, 69, 103, 137, 171, 205, 239, 1, 35, 69, 103, 137, 171, 205, 239, 1, 35, 69, 103, 137, 171, 205, 239, 1, 35, 69, 103, 137, 171, 205, 239>>
iex> privkey_to_wif(binprivkey)
{:ok, %{
wif: "KwFvTne98E1t3mTNAr8pKx67eUzFJWdSNPqPSfxMEtrueW7PcQzL",
privkey_bin: <<1, 35, 69, 103, 137, 171, 205, 239, 1, 35, 69, 103, 137, 171, 205, 239, 1, 35, 69, 103, 137, 171, 205, 239, 1, 35, 69, 103, 137, 171, 205, 239>>,
privkey_hex: "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF",
compressed: true,
network: :mainnet
}}
iex> privkey_to_wif(binprivkey, compressed: false, network: :testnet)
{:ok, %{
wif: "91bRE5Duv5h8kYhhTLhYRXijCiXWSpWwFNX6nndfuntBdPV2idD",
privkey_bin: <<1, 35, 69, 103, 137, 171, 205, 239, 1, 35, 69, 103, 137, 171, 205, 239, 1, 35, 69, 103, 137, 171, 205, 239, 1, 35, 69, 103, 137, 171, 205, 239>>,
privkey_hex: "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF",
compressed: false,
network: :testnet
}}
When binary private key has an unexpected length (not 64 bytes for hex format or 32 bytes for binary format) returns error:
iex> privkey_to_wif(<<1, 35, 69>>)
{:error, :incorrect_privkey_length}
When private key is out of recommended range will return error:
iex> maxprivkey = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140" |> Base.decode16!()
iex> privkey_to_wif(maxprivkey)
{:error, :ecc_out_range}
When private key is hexadecimal and have an unexpected case:
iex> privkey_to_wif("0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF", case: :lower)
{:error, :unexpected_hexadecimal_case}
wif_to_privkey(wif_type()) :: {:ok, privkey_result()} | {:error, atom()}
Returns the raw private key from a Wallet Import Format (WIF) string. Including metadata from WIF telling:
compressed
: If when generating the public key, should use compressed format or uncompressed.network
: Where the private key should be used. In mainnet, or testnet.
Examples
Converts from wif to raw private key.
iex> wif_to_privkey("KwFvTne98E1t3mTNAr8pKx67eUzFJWdSNPqPSfxMEtrueW7PcQzL")
{:ok, %{
wif: "KwFvTne98E1t3mTNAr8pKx67eUzFJWdSNPqPSfxMEtrueW7PcQzL",
privkey_bin: <<1, 35, 69, 103, 137, 171, 205, 239, 1, 35, 69, 103, 137, 171, 205, 239, 1, 35, 69, 103, 137, 171, 205, 239, 1, 35, 69, 103, 137, 171, 205, 239>>,
privkey_hex: "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF",
compressed: true,
network: :mainnet
}}
Expected errors:
Error if is base58check is another type other from WIF:
iex> wif_to_privkey("1CLrrRUwXswyF2EVAtuXyqdk4qb8DSUHCX")
{:error, :not_wif_version_prefix}
Error if checksum is not valid:
iex> wif_to_privkey("KyFvTne98E1t3mTNAr8pKx67eUzFJWdSNPqPSfxMEtrueW7PcQzL")
{:error, :checksum_incorrect}
Error if using an unvalid base58 character:
iex> wif_to_privkey("10Ol0Ol0Ol0Ol0Ol0Ol0OOlIIIIIII0OlI")
{:error, :incorrect_base58}