Caustic is an Elixir cryptocurrency library which contains algorithms used in Bitcoin, Ethereum, and other blockchains. It also includes a rich cryptography, number theory, and general mathematics class library. You can use Caustic to quickly implement your own crypto wallet or client. With the low-level math library, you can have fun with exploratory mathematics.
Warning: This library is developed for learning purposes. Please do not use for production.
Add to mix.exs
of your Elixir project:
defp deps do
[
{:caustic, "~> 0.1.22"}
]
end
And then run:
mix deps.get
You can generate Bitcoin private keys.
privkey = Caustic.Secp256k1.generate_private_key()
# 55129182198667841522063226112743062531539377180872956850932941251085402073984
privkey_base58check = Caustic.Utils.base58check_encode(<<privkey::size(256)>>, :private_key_wif, convert_from_hex: false)
# 5Jjxv41cLxb3hBZRr5voBB7zj77MDo7QVVLf3XgK2tpdAoTNq9n
You can then digitally sign a message.
pubkey = Caustic.Secp256k1.public_key(privkey)
# {6316467786437337873577388437635743649101330733943708346103893494005928771381, 36516277665018688612645564779200795235396005730419130160033716279021320193545}
message = "Hello, world!!!"
hash = Caustic.Utils.hash256(message)
signature = Caustic.Secp256k1.ecdsa_sign(hash, privkey)
Caustic.Secp256k1.ecdsa_verify?(pubkey, hash, signature) # true
Caustic has many functions to deal with integers and their properties. For example you can do primality testing.
first_primes = 1..20 |> Enum.filter(&Caustic.Utils.prime?/1)
# [2, 3, 5, 7, 11, 13, 17, 19]
So 7 is supposed to be a prime. Let's confirm by finding its divisors:
Caustic.Utils.divisors 7
# [1, 7]
This is in contrast to 6 for example, which has divisors other than 1 and itself:
Caustic.Utils.divisors 6
# [1, 2, 3, 6]
The sum of 6's divisors other than itself (its proper divisors) equals to 6 again. Those kinds of numbers are called perfect numbers.
Caustic.Utils.proper_divisors 6
# [1, 2, 3]
Caustic.Utils.proper_divisors_sum 6
# 6
Caustic.Utils.perfect? 6
# true
We can easily find other perfect numbers.
1..10000 |> Enum.filter(&Caustic.Utils.perfect?/1)
# [6, 28, 496, 8128]
There aren't that many of them, it seems...
Now back to our list of first primes. You can find the primitive roots of those primes:
first_primes |> Enum.map(&{&1, Caustic.Utils.primitive_roots(&1)})
# [
# {2, [1]},
# {3, [2]},
# {5, [2, 3]},
# {7, [3, 5]},
# {11, [2, 6, 7, 8]},
# {13, [2, 6, 7, 11]},
# {17, [3, 5, 6, 7, 10, 11, 12, 14]},
# {19, [2, 3, 10, 13, 14, 15]}
# ]
We can see that 5 is a primitive root of 7. It means that repeated exponentiation of 5 modulo 7 will generate all numbers relatively prime to 7. Let's confirm it:
Caustic.Utils.order_multiplicative 5, 7
# 6
1..6 |> Enum.map(&Caustic.Utils.pow_mod(5, &1, 7))
# [5, 4, 6, 2, 3, 1]
First we check the order of 5 modulo 7. It is 6, which means that 5^6 = 1 (mod 7), so further repeated multiplication (5^7 etc.) will just repeat previous values.
Then we calculate 5^1 to 5^6 (mod 7), and as expected it cycles through all numbers relatively prime to 7 because 5 is a primitive root of 7.
For more examples, please see the documentation of Caustic.Utils
.
Please send pull requests to https://github.com/agro1986/caustic
@agro1986 on Twitter