diff --git a/eqc_test/enacl_eqc.erl b/eqc_test/enacl_eqc.erl index a135c00..321e8d5 100644 --- a/eqc_test/enacl_eqc.erl +++ b/eqc_test/enacl_eqc.erl @@ -5,6 +5,10 @@ %% CRYPTO BOX %% --------------------------- +nonce() -> + Sz = enacl:box_nonce_size(), + binary(Sz). + prop_box_keypair() -> ?FORALL(_X, return(dummy), ok_box(enacl:box_keypair())). @@ -12,6 +16,25 @@ prop_box_keypair() -> ok_box({ok, _PK, _SK}) -> true; ok_box(_) -> false. +prop_box_correct() -> + ?FORALL({Msg, Nonce}, {binary(), nonce()}, + begin + {ok, PK1, SK1} = enacl:box_keypair(), + {ok, PK2, SK2} = enacl:box_keypair(), + CipherText = enacl:box(Msg, Nonce, PK2, SK1), + {ok, DecodedMsg} = enacl:box_open(CipherText, Nonce, PK1, SK2), + equals(Msg, DecodedMsg) + end). + +prop_box_failure_integrity() -> + ?FORALL({Msg, Nonce}, {binary(), nonce()}, + begin + {ok, PK1, SK1} = enacl:box_keypair(), + {ok, PK2, SK2} = enacl:box_keypair(), + CipherText = enacl:box(Msg, Nonce, PK2, SK1), + Err = enacl:box_open([<<"x">>, CipherText], Nonce, PK1, SK2), + equals(Err, {error, failed_verification}) + end). %% HASHING %% --------------------------- diff --git a/src/enacl.erl b/src/enacl.erl index 5dc54a0..c36f7e9 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -1,8 +1,14 @@ -module(enacl). -export([ - hash/1, - box_keypair/0 + box_keypair/0, + box/4, + box_open/4, + box_nonce_size/0 +]). + +-export([ + hash/1 ]). hash(Bin) -> @@ -11,3 +17,21 @@ hash(Bin) -> box_keypair() -> enacl_nif:crypto_box_keypair(). +box(Msg, Nonce, PK, SK) -> + enacl_nif:crypto_box([zerobytes(), Msg], Nonce, PK, SK). + +box_open(CipherText, Nonce, PK, SK) -> + case enacl_nif:crypto_box_open([box_zerobytes(), CipherText], Nonce, PK, SK) of + {error, Err} -> {error, Err}; + Bin when is_binary(Bin) -> {ok, Bin} + end. + +box_nonce_size() -> + enacl_nif:crypto_box_NONCEBYTES(). + +%% Helpers +zerobytes() -> + binary:copy(<<0>>, enacl_nif:crypto_box_ZEROBYTES()). + +box_zerobytes() -> + binary:copy(<<0>>, enacl_nif:crypto_box_BOXZEROBYTES()). diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index 0a7075b..f17271b 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -1,9 +1,22 @@ +%%% @doc module enacl_nif provides the low-level interface to the NaCl/Sodium NIFs. +%%% @end -module(enacl_nif). +%% Public key auth -export([ - crypto_hash/1, - crypto_box_keypair/0 + crypto_box_keypair/0, + crypto_box/4, + crypto_box_open/4, + crypto_box_NONCEBYTES/0, + crypto_box_ZEROBYTES/0, + crypto_box_BOXZEROBYTES/0 ]). + +%% Miscellaneous helper functions +-export([ + crypto_hash/1 +]). + -on_load(init/0). init() -> @@ -16,6 +29,16 @@ init() -> end, atom_to_list(?MODULE)), erlang:load_nif(SoName, 0). -crypto_hash(Input) when is_binary(Input) -> error({nif_not_loaded, ?MODULE}). -crypto_box_keypair() -> error({nif_not_loaded, ?MODULE}). +not_loaded() -> + error({nif_not_loaded, ?MODULE}). + +crypto_box_NONCEBYTES() -> not_loaded(). +crypto_box_ZEROBYTES() -> not_loaded(). +crypto_box_BOXZEROBYTES() -> not_loaded(). +crypto_box_keypair() -> not_loaded(). +crypto_box(_PaddedMsg, _Nonce, _PK, _SK) -> not_loaded(). +crypto_box_open(_CipherText, _Nonce, _PK, _SK) -> not_loaded(). + +crypto_hash(Input) when is_binary(Input) -> not_loaded(). +