Skip to content
This repository has been archived by the owner. It is now read-only.
master
Switch branches/tags
Go to file
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
doc
 
 
 
 
src
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

Soda Soda Hex Version Gitlab-CI Travis-CI License


This project is no longer maintained

Please use and contribute to enacl

therecanonlybeone

Libsodium bindings for Erlang

About

Soda provides Erlang bindings to the Sodium Crypto Library (libsodium).

Working with Soda is simple in both Erlang and Elixr.

  • Erlang
1> N = soda:nonce(aead_xchacha20poly1305_ietf).
<<115,97,120,157,28,208,118,165,137,95,122,152,195,49,52,
  188,73,136,216,201,77,183,29,144>>
2> {ok, H} = soda:password_hash("foo").
{ok,<<"$argon2id$v=19$m=65536,t=2,p=1$Isq7U9BICzjQKL7HhrpdtA$8WEFXpc6a3ef+DMZELmmxA23xTCQq9CpN6/NPHXBUPg">>}
2> true = soda:password_verify(H, "foo").
true
  • Elixir
iex(1)> n = :soda.nonce(:aead_xchacha20poly1305_ietf)
<<115,97,120,157,28,208,118,165,137,95,122,152,195,49,52,
  188,73,136,216,201,77,183,29,144>>
iex(2)> {:ok, h} = :soda.password_hash("foo")
{:ok,<<"$argon2id$v=19$m=65536,t=2,p=1$Isq7U9BICzjQKL7HhrpdtA$8WEFXpc6a3ef+DMZELmmxA23xTCQq9CpN6/NPHXBUPg">>}
iex(3)> true = :soda.password_verify(h, "foo")
true

Installation

Rebar3

{deps, [{soda, "1.1.1"}]}

Mix

def deps do
  [{:soda, "~> 1.1"}]
end

Usage

Soda

nonce/1

1> N = soda:nonce(aead_xchacha20poly1305_ietf).
<<115,97,120,157,28,208,118,165,137,95,122,152,195,49,52,
  188,73,136,216,201,77,183,29,144>>

rand/1

soda:rand(42).
<<83,247,61,202,83,171,99,56,51,108,141,82,255,186,41,26,
  215,4,229,148,72,204,131,248,8,86,196,104,95,...>>

password_hash/1 and password_verify/2

1> {ok, H} = soda:password_hash("thuper thecret").
{ok,<<"$argon2id$v=19$m=65536,t=2,p=1$rPQCfeJLuKMoLei+d5o9uA$7LsyBNEnYVq2JOpTgD2cil+swou5gvewoEjcuQznYq0">>}
2> true = soda:password_verify(H, "thuper thecret").
true

aead_encrypt/2 and aead_decrypt/4

1> {ok, Ciphered, Nonce, Key} = soda:aead_encrypt(<<"Secret Msg">>, <<"Additional Data">>).
{ok,<<183,123,21,95,51,26,85,197,41,226,96,91,26,28,16,
      110,85,123,18,239,29,57,11,30,228,61>>,
    <<238,32,82,106,137,223,37,173,68,177,216,210,169,168,126,
      245,10,247,27,161,127,195,217,24>>,
    <<8,108,139,115,235,95,95,44,128,74,18,186,2,207,2,83,79,
      53,115,239,12,118,198,100,198,...>>}
2> soda:aead_decrypt(Ciphered, <<"Additional Data">>, Nonce, Key).
{ok,<<"Secret Msg">>}

Generic Hashing

Single part

Without a key

1> {ok, Hash} = soda_api:hash(<<"Every book is a children's book if the kid can read!">>).
{ok,<<110,213,155,8,43,187,167,80,146,177,214,102,226,62,
      107,0,197,188,250,227,26,127,216,211,82,111,20,...>>}

With a key

  1> Key = soda:rand(16).
  <<210,27,222,99,117,191,249,46,192,189,137,37,59,128,142,38>>
  2> Data = <<"Every book is a children's book if the kid can read!">>.
  <<"Every book is a children's book if the kid can read!">>
  2> {ok, Hash} = soda_api:hash(Data, Key).
  {ok,<<46,245,69,115,197,167,214,2,175,251,181,113,130,
      234,222,98,228,42,249,24,59,129,29,107,213,124,46,...>>}
Multi-part

Without a key

1> {ok, State} = soda:hash_init().
{ok,#Ref<0.3118750307.3589668872.246381>}
2> Msg1 = <<"Any sufficiently complicated concurrent program in another language
contains an ad hoc informally-specified ">>.
<<"Any sufficiently complicated concurrent program in another language contains an ad hoc informally-specified ">>
3> {ok, State1} = soda:hash_update(State, Msg1).
{ok,#Ref<0.3118750307.3589668872.246382>}
4> Msg2 = <<"bug-ridden slow implementation of half of Erlang.">>.
<<"bug-ridden slow implementation of half of Erlang.">>
5> {ok, State2} = soda:hash_update(State1, Msg2).
{ok,#Ref<0.3118750307.3589668872.246383>}
6> {ok, Hash} = soda:hash_final(State2).
{ok,<<213,253,49,236,84,178,244,57,188,147,14,175,172,74,
      105,61,99,4,143,138,246,208,235,82,205,74,211,...>>}
7> Hex = soda:bin2hex(Hash).
<<"d5fd31ec54b2f439bc930eafac4a693d63048f8af6d0eb52cd4ad353e90fbc01">>

With a key

1> Key = <<"Virding's first rule of programming">>,
<<"Virding's first rule of programming">>,
2> {ok, State} = soda:hash_init(Key).
{ok,#Ref<0.791790418.1979056136.39831>}
3> Msg1 = <<"Any sufficiently complicated concurrent program in another language
contains an ad hoc informally-specified ">>.
<<"Any sufficiently complicated concurrent program in another language contains an ad hoc informally-specified">>
4> {ok, State1} = soda:hash_update(State, Msg1).
{ok,#Ref<0.791790418.1979056136.39832>}
5> Msg2 = <<"bug-ridden slow implementation of half of Erlang.">>.
<<"bug-ridden slow implementation of half of Erlang.">>
6> {ok, State2} = soda:hash_update(State1, Msg2).
{ok,#Ref<0.791790418.1979056136.39833>}
7> {ok, Hash} = soda:hash_final(State2).
{ok,<<103,191,97,168,121,250,16,57,59,220,113,55,230,119,
    126,141,93,102,86,130,143,198,54,102,23,180,219,...>>}
8> Hex = soda_api:bin2hex(Hash).
<<"67bf61a879fa10393bdc7137e6777e8d5d6656828fc6366617b4db25e93bfe41">>

Soda API

For advanced usage soda provides soda_api

AEAD constructions

XChaCha20-Poly1305 construction
  1. Generate a public nonce
1> N = soda_api:randombytes(24).
<<115,97,120,157,28,208,118,165,137,95,122,152,195,49,52,
  188,73,136,216,201,77,183,29,144>>
  1. Generate a secret key using the soda_api module
2> K = soda_api:aead_xchacha20poly1305_ietf_keygen().
<<234,19,163,89,73,193,122,110,11,196,215,227,56,193,126,
  110,228,27,49,107,19,123,43,168,255,60,92,13,49,...>>
  1. Encrypt a message with some non-confidential additional data and our secret key and nonce
  3> C = soda_api:aead_xchacha20poly1305_ietf_encrypt(<<"Hello, Mike?">>, <<"Hello, Joe.">>, N, K ).
  <<218,218,199,94,171,25,110,199,107,224,186,225,52,248,
    185,1,53,39,16,167,91,24,155,31,143,195,89,87>>
  1. Decrypt the ciphered message using our additional data, nonce, and key
  4> D = soda_api:aead_xchacha20poly1305_ietf_decrypt(C, <<"Hello, Joe.">>, N, K).
  <<"Hello, Mike?">>

Generic Hashing

Single part

Without a key

1> {ok, Hash} = soda_api:generichash(<<"Every book is a children's book if the kid can read!">>).
{ok,<<110,213,155,8,43,187,167,80,146,177,214,102,226,62,
    107,0,197,188,250,227,26,127,216,211,82,111,20,...>>}

With a key

1> Key = soda_api:randombytes(16).
<<210,27,222,99,117,191,249,46,192,189,137,37,59,128,142,38>>
2> Data = <<"Every book is a children's book if the kid can read!">>.
<<"Every book is a children's book if the kid can read!">>
3> {ok, Hash} = soda_api:generichash(<<"Every book is a children's book if the kid can read!">>, Key).
{ok,<<46,245,69,115,197,167,214,2,175,251,181,113,130,
    234,222,98,228,42,249,24,59,129,29,107,213,124,46,...>>}
Multi-part

Without a key

1> {ok, State} = soda_api:generichash_init().
{ok,#Ref<0.3118750307.3589668872.246381>}
2> Msg1 = <<"Any sufficiently complicated concurrent program in another language
contains an ad hoc informally-specified ">>.
<<"Any sufficiently complicated concurrent program in another language contains an ad hoc informally-specified ">>
3> {ok, State1} = soda_api:generichash_update(State,  Msg1).
{ok,#Ref<0.3118750307.3589668872.246382>}
4> Msg2 = <<"bug-ridden slow implementation of half of Erlang.">>.
<<"bug-ridden slow implementation of half of Erlang.">>
5> {ok, State2} = soda_api:generichash_update(State1, Msg).
{ok,#Ref<0.3118750307.3589668872.246383>}
6> {ok, Hash} = soda_api:generichash_final(State2).
{ok,<<213,253,49,236,84,178,244,57,188,147,14,175,172,74,
    105,61,99,4,143,138,246,208,235,82,205,74,211,...>>}
7> Hex = soda_api:bin2hex(Hash).
<<"d5fd31ec54b2f439bc930eafac4a693d63048f8af6d0eb52cd4ad353e90fbc01">>

With a key

1> {ok, State} = soda_api:generichash_init(<<"Virding's first rule of programming">>).
{ok,#Ref<0.791790418.1979056136.39831>}
2> Msg1 = <<"Any sufficiently complicated concurrent program in another language
contains an ad hoc informally-specified ">>.
<<"Any sufficiently complicated concurrent program in another language contains an ad hoc informally-specified ">>
3> {ok, State1} = soda_api:generichash_update(State, Msg1).
{ok,#Ref<0.791790418.1979056136.39832>}
4> Msg2 = <<"bug-ridden slow implementation of half of Erlang.">>.
<<"bug-ridden slow implementation of half of Erlang.">>
5> {ok, State2} = soda_api:generichash_update(State1, Msg2).
{ok,#Ref<0.791790418.1979056136.39833>}
6> {ok, Hash} = soda:generichash_final(State2).
{ok,<<103,191,97,168,121,250,16,57,59,220,113,55,230,119,
    126,141,93,102,86,130,143,198,54,102,23,180,219,...>>}
7> Hex = soda_api:bin2hex(Hash).
<<"67bf61a879fa10393bdc7137e6777e8d5d6656828fc6366617b4db25e93bfe41">>

Reference

Inspirado