Base58
provides two functions to
work with Base58 encoded strings: Base58.encode/1
and Base58.decode/1
encode/1
takes an Elixir binary (String, Number, etc.)
and returns a Base58 encoded String.
decode/1
receives a Base58 encoded String and returns a binary.
See the section What is an Elixir binary? for more information about the binary type in Elixir.
Open your mix.exs
file and add the following line to your deps
:
defp deps do
[
{:b58, "~> 1.0.2"},
]
end
and run mix deps.get
Base58.encode("foo")
"bQbp"
Base58.encode("hello") |> Base58.decode()
"hello"
See example/example.exs
file
for a simple example of how to use the module.
You can also run this example with mix run example/example.exs
When encoding an Integer
the value is converted to a String
before encoding
so when it is decoded it will be a string e.g:
Base58.encode(42) |> Base58.decode()
"42"
This isn't ideal if you expected an Integer
but there is no way to encode the type
of the data.
So if you know that you need it to be an int
,
convert it back to a numeric value with Base58.decode_to_int/1
:
iex(1)> Base58.encode(42) |> Base58.decode_to_int()
42
A base is a set of characters used for representing numbers. https://en.wikipedia.org/wiki/Base58
For example
- The base 2 (binary system) represents numbers with the digits
0 1
- The base 10 (decimal system) represents numbers with the digits
0 1 2 3 4 5 6 7 8 9
. - The base 16 (hexadecimal system) represents numbers with the digits
0 1 2 3 4 5 6 7 8 9 A B C D E F
The 2, 10, 16
are called radix and represent the number of unique digits in the base.
Bases are positional numeral systems. This means that the place of a digit matters, for example we can define the place for each digit of the number 423 as:
digit | place |
---|---|
3 | 0 |
2 | 1 |
4 | 2 |
To calculate the value of a number in a specific base to base 10, we are using the place of the digit, the radix and the function exponential as following:
423 in base b is 4 x b2 + 2 x b1 + 3 x b0
So 423 in base 10 is 4 x 102 + 2 x 101 + 3 x 100
another example on base 16 with the number F66: We know that F is 15 in base 10, then by using exponentials and places we have F66 is 15 x 162 + 6 x 161 + 6 * 160 which is 3942
To convert a decimal d to base b
- Get the remainder of d by b:
rem(d, b)
and note down the result. - Get the integer division of d by b:
d1 = div(d, b)
and repeat the step 1 withrem(d1, b)
- Stop this process when the division returns 0
- Match each number of the sequence of remainder to the base
For example 12 in base 2 is:
r0 = 0 = rem(12, 2)
d0 = 6 = div(12, 2)
r1 = 0 = rem(d0, 2) = rem(6,2)
d1 = 3 = div(6, 2)
r2 = 1 = rem(d1, 2) = rem(3, 2)
d2 = 1 = div(3, 2)
r3 = 1 = rem(d2, 2) = rem(1, 2)
d3 = 0 = div(1, 2) # stop the process
# 12 in base 2 is r3 r2 r1 r0 which is 1100
base58
represents number with the follwing character set:
123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
where
0 -> "1", 1 -> "2", ..., 57 -> "z"
If we take the process on the previous section with 65 and apply it with base58 we have:
r0 = 7 = rem(65, 58)
d0 = 1 = div(65, 58)
r1 = 1 = rem(1, 58)
d1 = 0 = div(1, 58) # stop the process
# r1 r0 is 1 7 and with the base58 characters 1 is 2 and 7 is 8
# So 65 in base 10 is 28 in base 58
Note that if a binary start with leading zeros then the zeros are represented as "1" in base58. So <<0, 0, 0, 1>> is defined as "1112" in base58.
from https://en.bitcoin.it/wiki/Base58Check_encoding
The leading character '1', which has a value of zero in base58, is reserved for representing an entire leading zero byte
For more information about the implementation of this module see the issue 1: How to encode a string to base58
Wikipedia page for Base: https://en.wikipedia.org/wiki/Radix
The base 58 character set is a subset of the base 64 where non-alphanumeric characters
have been removed and also 0OIl
letters to keep the string easily readable.
base 58 uses comes from Bitcoin and blockchain. It is also used with IPFS to create Content Identifier
Wikipedia page for base58: https://en.wikipedia.org/wiki/Base58
From https://elixir-lang.org/getting-started/binaries-strings-and-char-lists.html
A
binary
is a sequence of bytes
A byte is a sequence of eight bits (i.e a sequence of eight 0 or 1) For example the following are bytes with their decimal representation:
byte in base2 | decimal |
---|---|
00000001 | 1 |
00000010 | 2 |
00000011 | 3 |
00000100 | 4 |
In Elixir binary is represented and created with << >>
For example the sequence of bytes 00000001 00000010 00000011 00000100
is <<1, 2, 3, 4>>
in Elixir.
All Elixir Strings are a binaries but not all binaries are Strings.
A String is a binary where the numbers represent each letter in UTF8/unicode.
One trick to see the binary representation of a string is to add <<0>>
at the end of the string with the concatenation operator <>
:
"hello" <> <<0>>
<<104, 101, 108, 108, 111, 0>>
"hello" == <<104, 101, 108, 108, 111 >>
true
A binary in Elixir is different to a binary number which is the representation of a number in base2, e.g 110 represents 6
However 6 in Elixir is not a binary but an Integer.
You can use the Integer.to_string
function to see the representation of an integer in different base:
Integer.to_string(6, 2) # 6 as binary number in base 2
"110"
Integer.to_string(10, 2) # 10 as binary number in base 2
"1010"
Integer.to_string(10, 10) # 10 as a decimal number in base 10
"10"
Integer.to_string(10, 16) # 10 as an hexadecimal number in base 16
"A"
Integer.to_string(15, 16) # 15 as an hexadecimal number in base 16
"F"