defmodule BitcoinLib.Crypto.Wif do
@moduledoc """
WIF Bitcoin private key format management
Inspired by https://learnmeabitcoin.com/technical/wif
"""
alias BitcoinLib.Crypto
@mainnet 0x80
@testnet 0xEF
@doc """
Converts a raw private key to the WIF format
## Examples
iex> <<10, 141, 40, 107, 17, 185, 143, 108, 178, 88, 91, 98, 127, 244, 77, 18, 5,
...> 149, 96, 172, 212, 48, 220, 250, 18, 96, 239, 43, 217, 86, 147, 115>>
...> |> BitcoinLib.Crypto.Wif.from_bitstring
"KwaDo7PNi4XPMaABfSEo9rP6uviDUATAqvyjjWTcKp4fxdkVJWLe"
"""
@spec from_bitstring(bitstring()) :: String.t()
def from_bitstring(value) do
value
|> add_prefix
|> add_compressed
|> add_checksum
|> Base58.encode()
end
@doc """
Converts a WIF encoded private key into its binary format
## Examples
iex> "cThjSL4HkRECuDxUTnfAmkXFBEg78cufVBy3ZfEhKoxZo6Q38R5L"
...> |> BitcoinLib.Crypto.Wif.to_private_key()
<<0xb6a42d01917404b740f9ef9d5cef08e13f998011246874dd65c033c4669e7009::256>>
"""
@spec to_private_key(binary()) :: bitstring()
def to_private_key(wif) do
wif
|> Base58.decode()
|> decode_private_key
end
defp add_prefix(key) do
<<0x80>> <> key
end
defp add_compressed(key) do
key <> <<1>>
end
defp add_checksum(key) do
key <> Crypto.checksum(key)
end
defp decode_private_key(<<@mainnet::8, key::bitstring-256, _compressed?::8, _checksum::32>>) do
key
end
defp decode_private_key(<<@testnet::8, key::bitstring-256, _compressed?::8, _checksum::32>>) do
key
end
end