Packages

libsodium bindings for Erlang

Retired package: Deprecated - This version contained a breaking change

Current section

Files

Jump to
soda src soda.erl
Raw

src/soda.erl

%%% @author Bryan Paxton <starbelly@pobox.com>
%%% @doc soda module is the default interface which intends to provide
%%% a simple and inuitive interface to soda_api, which in turn provides a
%%% lower level interface to libsodium.
%%% For advanced usage please refer to soda_api.
%%% @end.
-module(soda).
% Helpers
-export([nonce/1, rand/1]).
% Password hashing
-export([hash/3, hash_init/1, hash_init/2, hash_update/2, hash_final/2, password_hash/1, password_verify/2]).
% AEAD
-export([aead_encrypt/2, aead_decrypt/4]).
-define(NONCE_SIZES,
#{
aead_xchacha20poly1305_ietf => 24
}
).
%% @doc
%% The aead_encrypt/2 function returns an encrypted binary created from the
%% message `Msg' and non-confidential additional data `Ad'.
%% The additional data may be 0 byte if no additional data is required.
%% Returns the ciphered text, 192 bit nonce and a secret key.
%% @end
-spec aead_encrypt(binary(), binary()) -> {ok, binary(), binary(), binary()}.
aead_encrypt(Msg, Ad) when is_binary(Msg) andalso is_binary(Ad) ->
N = soda:nonce(aead_xchacha20poly1305_ietf),
K = soda_api:aead_xchacha20poly1305_ietf_keygen(),
C = soda_api:aead_xchacha20poly1305_ietf_encrypt(Msg, Ad, N, K),
{ok, C, N, K}.
%% @doc
%% The aead_decrypt/4 function returns a decrypted message using the supplied
%% cipher text, non-confidential Addition Data, Nonce, and Key.
%% @end
-spec aead_decrypt(binary(), binary(), binary(), binary()) -> {ok, binary()}.
aead_decrypt(C, Ad, N, K) when is_binary(C) andalso is_binary(Ad) andalso
is_binary(N) andalso size(N) == 24 andalso
is_binary(K) andalso size(K) == 32 ->
M = soda_api:aead_xchacha20poly1305_ietf_decrypt(C, Ad, N, K),
{ok, M}.
%% @doc
%% The hash/3 function returns a computed fixed-length finger print (hash)
%% using the supplied message, key, and size. Size must be between 32 and 64.
%% @end
hash(Msg, Key, Size) when is_binary(Msg) ->
{ok, Hash} = soda_api:generichash(Size, Msg, Key),
{ok, Hash}.
%% @doc
%% The hash_init/1 initializes state with no key for a multi-part hash
%% operation. Updates to the state may be perfomed using returned reference and hash_update/2
%% @end
-spec hash_init(integer()) -> {ok, reference()} | {error, term()}.
hash_init(Size) ->
soda_api:generichash_init(Size).
%% @doc
%% The hash_init/2 initializes state with the supplied key for a multi-part hash
%% operation. Updates to the state may be perfomed using returned reference and hash_update/2
%% @end
-spec hash_init(binary(), integer()) -> {ok, reference()} | {error, term()}.
hash_init(Key, Size) ->
soda_api:generichash_init(Size, Key).
%% @doc
%% The hash_update/2 updates the referenced state with the supplied message.
%% @end
-spec hash_update(reference(), binary()) -> ok | {error, term()}.
hash_update(State, Msg) when is_reference(State)
andalso is_binary(Msg) ->
soda_api:generichash_update(State, Msg).
%% @doc
%% The hash_final/2 functions returns a complete hash given a reference to a
%% hash state and an output size.
%% @end
-spec hash_final(reference(), integer()) -> {ok, binary()} | {error, term()}.
hash_final(State, Size) when is_reference(State) ->
soda_api:generichash_final(Size, State).
%% @doc
%% The following nonce types are currently supported:
%% `aead_xchacha20poly1305_ietf'
%% @end
-spec nonce(atom()) -> binary() | {error, term()}.
nonce(NonceType) when is_atom(NonceType) ->
case maps:get(NonceType, ?NONCE_SIZES, none) of
none -> {error, unknown_nonce};
Size -> soda_api:randombytes(Size)
end.
%% @doc
%% Creates a hashed password suitable for storage (e.g., RDMBS, Mnesia, etc.).
%% All parameters needed to verify the password are stored in the returned
%% binary.
%% @end
-spec password_hash(binary()) -> {ok, binary()} | {error, term()}.
password_hash(Str) when is_binary(Str) ->
soda_api:pwhash_str(Str).
%% @doc
%% Verifies a password against a hashed password as created by `password_hash/1'
%% @end
-spec password_verify(binary(), binary()) -> boolean().
password_verify(HashStr, Str) when is_binary(HashStr)
andalso is_binary(Str) ->
soda_api:pwhash_str_verify(HashStr, Str).
%% @doc
%% Generate a binary consisting a sequence of `N' unpredictable random bytes.
%% @end
-spec rand(non_neg_integer()) -> binary().
rand(N) when is_integer(N) andalso N >= 0 ->
soda_api:randombytes(N).