# Area58check
## What is Area58?
Area58 is a library to encode and decode base58check. Base58check is
used in Bitcoin whenever there is a need for a user to read or
transcribe a number, such a bitcoin adresses, encrypted key, private
key, or script hash.
## What is NOT Area58?
This can't be used to generate bitcoin address from a private key. It's
only a base58check encoder/decoder. But it's easy to generate a bitcoin
address from the private key.
Example: If you want to generate a (uncompressed) bitcoin address using
this library you can...
iex> privkey = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" |> Base.decode16!()
iex> {uncompressed_pubkey, _priv_key} = :crypto.generate_key(:ecdh, :crypto.ec_curve(:secp256k1), privkey)
iex> uncompressed_pubkey = :crypto.hash(:ripemd160, :crypto.hash(:sha256, uncompressed_pubkey))
iex> Area58check.encode(uncompressed_pubkey, version: <<0>>)
%{encoded: "1CLrrRUwXswyF2EVAtuXyqdk4qb8DSUHCX",
version: :p2pkh,
version_bin: <<0>>}
or you can use another library that does all that for you.
## What is base58check?
#### Encoding
Base58 charset is based on easy to trancribe characters, upper and
lower case letters and numbers excluding `0`, `O`, `l`, `I`.
#### Bitcoin version prefixes
Usually there is a version (binary number) to signal what kind of string
is being encoded.
[list of bitcoin prefixes](https://en.bitcoin.it/wiki/List_of_address_prefixes)
Example: for standard bitcoin address, is used the hexadecimal
number 0x00, for compressed WIF (allows to import a private key in
bitcoin) is used 0x80, etc.
#### Checksum
When a string is encoded, 4 bytes (or 32bits), are added to the end by
`Area58check.encode` function as a checksum to make sure that no
characters were wrongly transcribed. This checksum is not meant to allow
to fix a wrong transcribed string, but it allows to verify if string is
correct or not.
## Usage
#### Encoding
Encode a private key into WIF (Wallet Import Format):
iex> privkey = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" |> Base.decode16!()
iex> Area58check.encode(privkey, version: :wif )
%{encoded: "5HpneLQNKrcznVCQpzodYwAmZ4AoHeyjuRf9iAHAa498rP5kuWb",
version: :wif,
version_bin: <<128>>}
iex> Area58check.encode(privkey, version: [128] )
%{encoded: "5HpneLQNKrcznVCQpzodYwAmZ4AoHeyjuRf9iAHAa498rP5kuWb",
version: :wif,
version_bin: <<128>>}
iex> Area58check.encode(privkey, version: <<128>>)
%{encoded: "5HpneLQNKrcznVCQpzodYwAmZ4AoHeyjuRf9iAHAa498rP5kuWb",
version: :wif,
version_bin: <<128>>}
iex> Area58check.encode(privkey, version: 0x80)
%{encoded: "5HpneLQNKrcznVCQpzodYwAmZ4AoHeyjuRf9iAHAa498rP5kuWb",
version: :wif,
version_bin: <<128>>}
Encode a public key into an address:
iex> {uncompressed_pubkey, _priv_key} = :crypto.generate_key(:ecdh, :crypto.ec_curve(:secp256k1), privkey)
iex> derived_uncomp_pubkey = :crypto.hash(:ripemd160, :crypto.hash(:sha256, uncompressed_pubkey))
iex> Area58check.encode(derived_uncomp_pubkey, version: 0x00)
%{encoded: "1CLrrRUwXswyF2EVAtuXyqdk4qb8DSUHCX",
version: :p2pkh,
version_bin: <<0>>}
Error when version is unknown:
iex> Area58check.encode(privkey, version: :jhkdsfajhkfdasjhkfd)
** (ArgumentError) :jhkdsfajhkfdasjhkfd is not a recognized version.
You can either pass a charlist (ex: [4, 136, 178, 30]), number (ex:
70617039), hexadecimal (ex: 0x043587CF), binary version (ex: <<4,
136, 178, 30>>), or a recognized atom like any of: :bip32_privkey,
:bip32_pubkey, :p2pkh, :p2sh, :tesnet_bip32_privkey,
:tesnet_bip32_pubkey, :tesnet_p2pkh, :tesnet_p2sh, :tesnet_wif, :wif
#### Decoding
Decoding strings encoded with base58check:
iex> Area58check.decode("1CLrrRUwXswyF2EVAtuXyqdk4qb8DSUHCX")
{:ok,
%{decoded: <<124, 106, 230, 190, 9, 150, 81, 133, 169, 75, 13, 161, 139, 201,
42, 157, 252, 238, 97, 23>>,
version: :p2pkh,
version_bin: <<0>>}}
iex> Area58check.decode("5HpneLQNKrcznVCQpzodYwAmZ4AoHeyjuRf9iAHAa498rP5kuWb")
{:ok,
%{decoded: <<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>>,
version: :wif,
version_bin: <<0>>}}
If checksum is not valid returns error:
iex> Area58check.decode("1CheckSumError")
{:error, :checksum_incorrect}
If contains a non valid character like `0`, `O`, `l`, `I`, returns
error:
iex> Area58check.decode("ContainsInvalidCharacter0")
{:error, :incorrect_base58}
## Installation
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `area58check` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:area58check, "~> 0.1.0"},
]
end
```
The docs can be found at
[https://hexdocs.pm/area58](https://hexdocs.pm/area58).