Decide on an even better API
This commit is contained in:
parent
aa2c69529a
commit
59b94439d1
10
CHANGELOG.md
10
CHANGELOG.md
@ -7,12 +7,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||
|
||||
## [TODO]
|
||||
|
||||
- Go through all calls and make them return {ok, _} | {error, _} if applicable.
|
||||
- Go through all calls and make them return streamlined exceptions if applicable.
|
||||
Pretty large change, but OTOH, this ought to happen before a 1.0 release as well.
|
||||
- AEAD
|
||||
- enacl
|
||||
- hash
|
||||
- kx
|
||||
- generichash
|
||||
- pwhash
|
||||
- randombytes
|
||||
- secret
|
||||
@ -25,8 +26,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||
## [Unreleased]
|
||||
|
||||
### Compatibility
|
||||
- Many functions returned the type `value() | {error, term()}`. They have been
|
||||
updated to return the more erlang-idiomatic `{ok, value()} | {error, term()}`.
|
||||
- Some functions have been streamlined to badarg in certain cases where it made more
|
||||
sense to do so than returning back an error to the caller.
|
||||
- Functions generally don't return error values for internal errors. They now raise
|
||||
exceptions when this happens. If you can't allocate a binary, there is usually not
|
||||
much the programmer can do with that information, sans crashing.
|
||||
- If you used `aead_chacha20poly1305_*` functions, please read through the changelog
|
||||
carefully as we have made changes to these functions. TL;DR: look for
|
||||
`aead_chacha20poly1305_ietf_*` but note it is *not* just a simple substitution
|
||||
|
@ -6,3 +6,7 @@ ERL_NIF_TERM enacl_error_tuple(ErlNifEnv *env, char *error_atom) {
|
||||
return enif_make_tuple2(env, enif_make_atom(env, "error"),
|
||||
enif_make_atom(env, error_atom));
|
||||
}
|
||||
|
||||
ERL_NIF_TERM enacl_internal_error(ErlNifEnv *env) {
|
||||
return enif_raise_exception(env, enif_make_atom(env, "internal_error"));
|
||||
}
|
@ -9,5 +9,6 @@
|
||||
#define ATOM_FALSE "false"
|
||||
|
||||
ERL_NIF_TERM enacl_error_tuple(ErlNifEnv *, char *);
|
||||
ERL_NIF_TERM enacl_internal_error(ErlNifEnv *);
|
||||
|
||||
#endif
|
||||
|
@ -90,21 +90,17 @@ ERL_NIF_TERM enacl_crypto_box(ErlNifEnv *env, int argc,
|
||||
goto bad_arg;
|
||||
|
||||
if (!enif_alloc_binary(padded_msg.size, &result)) {
|
||||
ret = enacl_error_tuple(env, "alloc_failed");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (0 != crypto_box(result.data, padded_msg.data, padded_msg.size, nonce.data,
|
||||
pk.data, sk.data)) {
|
||||
ret = enacl_error_tuple(env, "box_error");
|
||||
goto release;
|
||||
}
|
||||
|
||||
ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK);
|
||||
ERL_NIF_TERM ret_bin = enif_make_sub_binary(
|
||||
env, enif_make_binary(env, &result), crypto_box_BOXZEROBYTES,
|
||||
ret = enif_make_sub_binary(env, enif_make_binary(env, &result),
|
||||
crypto_box_BOXZEROBYTES,
|
||||
padded_msg.size - crypto_box_BOXZEROBYTES);
|
||||
ret = enif_make_tuple2(env, ret_ok, ret_bin);
|
||||
|
||||
goto done;
|
||||
|
||||
@ -112,6 +108,8 @@ bad_arg:
|
||||
return enif_make_badarg(env);
|
||||
release:
|
||||
enif_release_binary(&result);
|
||||
err:
|
||||
ret = enacl_internal_error(env);
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
@ -136,7 +134,7 @@ ERL_NIF_TERM enacl_crypto_box_open(ErlNifEnv *env, int argc,
|
||||
}
|
||||
|
||||
if (!enif_alloc_binary(padded_ciphertext.size, &result)) {
|
||||
return enacl_error_tuple(env, "alloc_failed");
|
||||
return enacl_internal_error(env);
|
||||
}
|
||||
|
||||
if (0 != crypto_box_open(result.data, padded_ciphertext.data,
|
||||
@ -168,18 +166,18 @@ ERL_NIF_TERM enacl_crypto_box_beforenm(ErlNifEnv *env, int argc,
|
||||
}
|
||||
|
||||
if (!enif_alloc_binary(crypto_box_BEFORENMBYTES, &k)) {
|
||||
return enacl_error_tuple(env, "alloc_failed");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (0 != crypto_box_beforenm(k.data, pk.data, sk.data)) {
|
||||
// error
|
||||
enif_release_binary(&k);
|
||||
return enacl_error_tuple(env, "error_gen_shared_secret");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK);
|
||||
ERL_NIF_TERM ret_bin = enif_make_binary(env, &k);
|
||||
return enif_make_tuple2(env, ret_ok, ret_bin);
|
||||
return enif_make_binary(env, &k);
|
||||
err:
|
||||
return enacl_internal_error(env);
|
||||
}
|
||||
|
||||
ERL_NIF_TERM enacl_crypto_box_afternm(ErlNifEnv *env, int argc,
|
||||
@ -196,16 +194,14 @@ ERL_NIF_TERM enacl_crypto_box_afternm(ErlNifEnv *env, int argc,
|
||||
}
|
||||
|
||||
if (!enif_alloc_binary(m.size, &result)) {
|
||||
return enacl_error_tuple(env, "alloc_failed");
|
||||
return enacl_internal_error(env);
|
||||
}
|
||||
|
||||
crypto_box_afternm(result.data, m.data, m.size, nonce.data, k.data);
|
||||
|
||||
ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK);
|
||||
ERL_NIF_TERM ret_bin = enif_make_sub_binary(
|
||||
env, enif_make_binary(env, &result), crypto_box_BOXZEROBYTES,
|
||||
return enif_make_sub_binary(env, enif_make_binary(env, &result),
|
||||
crypto_box_BOXZEROBYTES,
|
||||
m.size - crypto_box_BOXZEROBYTES);
|
||||
return enif_make_tuple2(env, ret_ok, ret_bin);
|
||||
}
|
||||
|
||||
ERL_NIF_TERM enacl_crypto_box_open_afternm(ErlNifEnv *env, int argc,
|
||||
@ -222,7 +218,7 @@ ERL_NIF_TERM enacl_crypto_box_open_afternm(ErlNifEnv *env, int argc,
|
||||
}
|
||||
|
||||
if (!enif_alloc_binary(m.size, &result)) {
|
||||
return enacl_error_tuple(env, "alloc_failed");
|
||||
return enacl_internal_error(env);
|
||||
}
|
||||
|
||||
if (0 != crypto_box_open_afternm(result.data, m.data, m.size, nonce.data,
|
||||
@ -250,14 +246,12 @@ ERL_NIF_TERM enacl_crypto_box_seal(ErlNifEnv *env, int argc,
|
||||
}
|
||||
|
||||
if (!enif_alloc_binary(msg.size + crypto_box_SEALBYTES, &ciphertext)) {
|
||||
return enacl_error_tuple(env, "alloc_failed");
|
||||
return enacl_internal_error(env);
|
||||
}
|
||||
|
||||
crypto_box_seal(ciphertext.data, msg.data, msg.size, key.data);
|
||||
|
||||
ERL_NIF_TERM ret_ok = enif_make_atom(env, ATOM_OK);
|
||||
ERL_NIF_TERM ret_bin = enif_make_binary(env, &ciphertext);
|
||||
return enif_make_tuple2(env, ret_ok, ret_bin);
|
||||
return enif_make_binary(env, &ciphertext);
|
||||
}
|
||||
|
||||
ERL_NIF_TERM enacl_crypto_box_seal_open(ErlNifEnv *env, int argc,
|
||||
@ -276,7 +270,7 @@ ERL_NIF_TERM enacl_crypto_box_seal_open(ErlNifEnv *env, int argc,
|
||||
}
|
||||
|
||||
if (!enif_alloc_binary(ciphertext.size - crypto_box_SEALBYTES, &msg)) {
|
||||
return enacl_error_tuple(env, "alloc_failed");
|
||||
return enacl_internal_error(env);
|
||||
}
|
||||
|
||||
if (crypto_box_seal_open(msg.data, ciphertext.data, ciphertext.size, pk.data,
|
||||
|
@ -15,7 +15,7 @@ ERL_NIF_TERM enif_randombytes(ErlNifEnv *env, int argc,
|
||||
}
|
||||
|
||||
if (!enif_alloc_binary(req_size, &result)) {
|
||||
return enacl_error_tuple(env, "alloc_failed");
|
||||
return enacl_internal_error(env);
|
||||
}
|
||||
|
||||
randombytes(result.data, result.size);
|
||||
|
@ -183,10 +183,10 @@ prop_box_correct() ->
|
||||
begin
|
||||
case v_iodata(Msg) andalso nonce_valid(Nonce) andalso keypair_valid(PK1, SK1) andalso keypair_valid(PK2, SK2) of
|
||||
true ->
|
||||
{ok, Key} = enacl:box_beforenm(PK2, SK1),
|
||||
{ok, Key} = enacl:box_beforenm(PK1, SK2),
|
||||
{ok, CipherText} = enacl:box(Msg, Nonce, PK2, SK1),
|
||||
{ok, CipherText} = enacl:box_afternm(Msg, Nonce, Key),
|
||||
Key = enacl:box_beforenm(PK2, SK1),
|
||||
Key = enacl:box_beforenm(PK1, SK2),
|
||||
CipherText = enacl:box(Msg, Nonce, PK2, SK1),
|
||||
CipherText = enacl:box_afternm(Msg, Nonce, Key),
|
||||
{ok, DecodedMsg} = enacl:box_open(CipherText, Nonce, PK1, SK2),
|
||||
{ok, DecodedMsg} = enacl:box_open_afternm(CipherText, Nonce, Key),
|
||||
equals(iolist_to_binary(Msg), DecodedMsg);
|
||||
@ -210,8 +210,8 @@ prop_box_failure_integrity() ->
|
||||
andalso keypair_valid(PK1, SK1)
|
||||
andalso keypair_valid(PK2, SK2) of
|
||||
true ->
|
||||
{ok, Key} = enacl:box_beforenm(PK2, SK1),
|
||||
{ok, CipherText} = enacl:box(Msg, Nonce, PK2, SK1),
|
||||
Key = enacl:box_beforenm(PK2, SK1),
|
||||
CipherText = enacl:box(Msg, Nonce, PK2, SK1),
|
||||
Err = enacl:box_open([<<"x">>, CipherText], Nonce, PK1, SK2),
|
||||
Err = enacl:box_open_afternm([<<"x">>, CipherText], Nonce, Key),
|
||||
equals(Err, {error, failed_verification});
|
||||
@ -431,7 +431,7 @@ prop_seal_box_failure_integrity() ->
|
||||
begin
|
||||
case v_iodata(Msg) andalso keypair_valid(PK1, SK1) of
|
||||
true ->
|
||||
{ok, CT} = enacl:box_seal(Msg, PK1),
|
||||
CT = enacl:box_seal(Msg, PK1),
|
||||
Err = enacl:box_seal_open([<<"x">>, CT], PK1, SK1),
|
||||
equals(Err, {error, failed_verification});
|
||||
false ->
|
||||
@ -450,7 +450,7 @@ prop_seal_box_correct() ->
|
||||
begin
|
||||
case v_iodata(Msg) andalso keypair_valid(PK1, SK1) of
|
||||
true ->
|
||||
{ok, SealedCipherText} = enacl:box_seal(Msg, PK1),
|
||||
SealedCipherText = enacl:box_seal(Msg, PK1),
|
||||
{ok, DecodedMsg} = enacl:box_seal_open(SealedCipherText, PK1, SK1),
|
||||
equals(iolist_to_binary(Msg), DecodedMsg);
|
||||
false ->
|
||||
|
@ -453,7 +453,7 @@ box_keypair() ->
|
||||
%% Encrypt a `Msg' to the party identified by public key `PK' using your own secret key `SK' to
|
||||
%% authenticate yourself. Requires a `Nonce' in addition. Returns the ciphered message.
|
||||
%% @end
|
||||
-spec box(Msg, Nonce, PK, SK) -> {ok, CipherText} | {error, term()}
|
||||
-spec box(Msg, Nonce, PK, SK) -> CipherText
|
||||
when
|
||||
Msg :: iodata(),
|
||||
Nonce :: binary(),
|
||||
@ -481,7 +481,7 @@ box_open(CipherText, Nonce, PK, SK) ->
|
||||
|
||||
%% @doc box_beforenm/2 precomputes a box shared key for a PK/SK keypair
|
||||
%% @end
|
||||
-spec box_beforenm(PK, SK) -> {ok, binary()} | {error, term()}
|
||||
-spec box_beforenm(PK, SK) -> binary()
|
||||
when
|
||||
PK :: binary(),
|
||||
SK :: binary().
|
||||
@ -496,7 +496,7 @@ box_beforenm(PK, SK) ->
|
||||
%% if you had called `box(M, Nonce, PK, SK)'. Except that it avoids computations in the elliptic curve Curve25519,
|
||||
%% and thus is a much faster operation.
|
||||
%% @end
|
||||
-spec box_afternm(Msg, Nonce, K) -> {ok, CipherText} | {error, term()}
|
||||
-spec box_afternm(Msg, Nonce, K) -> CipherText
|
||||
when
|
||||
Msg :: iodata(),
|
||||
Nonce :: binary(),
|
||||
@ -692,7 +692,7 @@ box_secret_key_bytes() ->
|
||||
%% keypair and then uses `box'. Ephemeral public key will sent to other party. Returns the
|
||||
%% enciphered message `SealedCipherText' which includes ephemeral public key at head.
|
||||
%% @end
|
||||
-spec box_seal(Msg, PK) -> {ok, SealedCipherText} | {error, term()}
|
||||
-spec box_seal(Msg, PK) -> SealedCipherText
|
||||
when
|
||||
Msg :: iodata(),
|
||||
PK :: binary(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user