Add chacha stream function access.
This commit is contained in:
parent
ca005d32f9
commit
4d5524db61
@ -641,6 +641,16 @@ ERL_NIF_TERM enif_crypto_secretbox_BOXZEROBYTES(ErlNifEnv *env, int argc, ERL_NI
|
||||
return enif_make_int64(env, crypto_secretbox_BOXZEROBYTES);
|
||||
}
|
||||
|
||||
static
|
||||
ERL_NIF_TERM enif_crypto_stream_chacha20_KEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
|
||||
return enif_make_int64(env, crypto_stream_chacha20_KEYBYTES);
|
||||
}
|
||||
|
||||
static
|
||||
ERL_NIF_TERM enif_crypto_stream_chacha20_NONCEBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
|
||||
return enif_make_int64(env, crypto_stream_chacha20_NONCEBYTES);
|
||||
}
|
||||
|
||||
static
|
||||
ERL_NIF_TERM enif_crypto_stream_KEYBYTES(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
|
||||
return enif_make_int64(env, crypto_stream_KEYBYTES);
|
||||
@ -756,6 +766,61 @@ ERL_NIF_TERM enif_crypto_secretbox_open(ErlNifEnv *env, int argc, ERL_NIF_TERM c
|
||||
padded_ciphertext.size - crypto_secretbox_ZEROBYTES);
|
||||
}
|
||||
|
||||
static
|
||||
ERL_NIF_TERM enif_crypto_stream_chacha20(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
|
||||
ErlNifBinary c, n, k;
|
||||
ErlNifUInt64 clen;
|
||||
|
||||
if (
|
||||
(argc != 3) ||
|
||||
(!enif_get_uint64(env, argv[0], &clen)) ||
|
||||
(!enif_inspect_binary(env, argv[1], &n)) ||
|
||||
(!enif_inspect_binary(env, argv[2], &k))) {
|
||||
return enif_make_badarg(env);
|
||||
}
|
||||
|
||||
if (
|
||||
(k.size != crypto_stream_chacha20_KEYBYTES) ||
|
||||
(n.size != crypto_stream_chacha20_NONCEBYTES)) {
|
||||
return enif_make_badarg(env);
|
||||
}
|
||||
|
||||
if (!enif_alloc_binary(clen, &c)) {
|
||||
return nacl_error_tuple(env, "alloc_failed");
|
||||
}
|
||||
|
||||
crypto_stream_chacha20(c.data, c.size, n.data, k.data);
|
||||
|
||||
return enif_make_binary(env, &c);
|
||||
}
|
||||
|
||||
static
|
||||
ERL_NIF_TERM enif_crypto_stream_chacha20_xor(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
|
||||
ErlNifBinary c, m, n, k;
|
||||
|
||||
if (
|
||||
(argc != 3) ||
|
||||
(!enif_inspect_iolist_as_binary(env, argv[0], &m)) ||
|
||||
(!enif_inspect_binary(env, argv[1], &n)) ||
|
||||
(!enif_inspect_binary(env, argv[2], &k))) {
|
||||
return enif_make_badarg(env);
|
||||
}
|
||||
|
||||
if (
|
||||
(k.size != crypto_stream_chacha20_KEYBYTES) ||
|
||||
(n.size != crypto_stream_chacha20_NONCEBYTES)) {
|
||||
return enif_make_badarg(env);
|
||||
}
|
||||
|
||||
if (!enif_alloc_binary(m.size, &c)) {
|
||||
return nacl_error_tuple(env, "alloc_failed");
|
||||
}
|
||||
|
||||
crypto_stream_chacha20_xor(c.data, m.data, m.size, n.data, k.data);
|
||||
|
||||
return enif_make_binary(env, &c);
|
||||
}
|
||||
|
||||
static
|
||||
ERL_NIF_TERM enif_crypto_stream(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
|
||||
ErlNifBinary c, n, k;
|
||||
@ -1071,6 +1136,13 @@ static ErlNifFunc nif_funcs[] = {
|
||||
{"crypto_secretbox_open_b", 3, enif_crypto_secretbox_open},
|
||||
{"crypto_secretbox_open", 3, enif_crypto_secretbox_open, ERL_NIF_DIRTY_JOB_CPU_BOUND},
|
||||
|
||||
{"crypto_stream_chacha20_KEYBYTES", 0, enif_crypto_stream_chacha20_KEYBYTES},
|
||||
{"crypto_stream_chacha20_NONCEBYTES", 0, enif_crypto_stream_chacha20_NONCEBYTES},
|
||||
{"crypto_stream_chacha20_b", 3, enif_crypto_stream_chacha20},
|
||||
{"crypto_stream_chacha20", 3, enif_crypto_stream_chacha20, ERL_NIF_DIRTY_JOB_CPU_BOUND},
|
||||
{"crypto_stream_chacha20_xor_b", 3, enif_crypto_stream_chacha20_xor},
|
||||
{"crypto_stream_chacha20_xor", 3, enif_crypto_stream_chacha20_xor, ERL_NIF_DIRTY_JOB_CPU_BOUND},
|
||||
|
||||
{"crypto_stream_KEYBYTES", 0, enif_crypto_stream_KEYBYTES},
|
||||
{"crypto_stream_NONCEBYTES", 0, enif_crypto_stream_NONCEBYTES},
|
||||
{"crypto_stream_b", 3, enif_crypto_stream},
|
||||
|
@ -49,6 +49,11 @@
|
||||
secretbox/3,
|
||||
secretbox_open/3,
|
||||
|
||||
stream_chacha20_key_size/0,
|
||||
stream_chacha20_nonce_size/0,
|
||||
stream_chacha20/3,
|
||||
stream_chacha20_xor/3,
|
||||
|
||||
stream_key_size/0,
|
||||
stream_nonce_size/0,
|
||||
stream/3,
|
||||
@ -129,6 +134,8 @@
|
||||
-define(S_ZEROBYTES, <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>). %% 32 bytes
|
||||
-define(CRYPTO_SECRETBOX_BOXZEROBYTES, 16).
|
||||
-define(S_BOXZEROBYTES, <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>). %% 16 bytes
|
||||
-define(CRYPTO_STREAM_CHACHA20_KEYBYTES, 32).
|
||||
-define(CRYPTO_STREAM_CHACHA20_NONCEBYTES, 8).
|
||||
-define(CRYPTO_STREAM_KEYBYTES, 32).
|
||||
-define(CRYPTO_STREAM_NONCEBYTES, 24).
|
||||
|
||||
@ -141,6 +148,8 @@ verify() ->
|
||||
?S_BOXZEROBYTES),
|
||||
|
||||
Verifiers = [
|
||||
{crypto_stream_chacha20_KEYBYTES, ?CRYPTO_STREAM_CHACHA20_KEYBYTES},
|
||||
{crypto_stream_chacha20_NONCEBYTES, ?CRYPTO_STREAM_CHACHA20_NONCEBYTES},
|
||||
{crypto_stream_KEYBYTES, ?CRYPTO_STREAM_KEYBYTES},
|
||||
{crypto_stream_NONCEBYTES, ?CRYPTO_STREAM_NONCEBYTES},
|
||||
{crypto_box_ZEROBYTES, ?CRYPTO_BOX_ZEROBYTES},
|
||||
@ -501,6 +510,63 @@ secretbox_nonce_size() ->
|
||||
secretbox_key_size() ->
|
||||
enacl_nif:crypto_secretbox_KEYBYTES().
|
||||
|
||||
%% @doc stream_chacha20_nonce_size/0 returns the byte size of the nonce for streams
|
||||
%% @end
|
||||
-spec stream_chacha20_nonce_size() -> pos_integer().
|
||||
stream_chacha20_nonce_size() -> ?CRYPTO_STREAM_CHACHA20_NONCEBYTES.
|
||||
|
||||
%% @doc stream_key_size/0 returns the byte size of the key for streams
|
||||
%% @end
|
||||
-spec stream_chacha20_key_size() -> pos_integer().
|
||||
stream_chacha20_key_size() -> ?CRYPTO_STREAM_CHACHA20_KEYBYTES.
|
||||
|
||||
%% @doc stream_chacha20/3 produces a cryptographic stream suitable for secret-key encryption
|
||||
%%
|
||||
%% <p>Given a positive `Len' a `Nonce' and a `Key', the stream_chacha20/3 function will return an unpredictable cryptographic stream of bytes
|
||||
%% based on this output. In other words, the produced stream is indistinguishable from a random stream. Using this stream one
|
||||
%% can XOR it with a message in order to produce a encrypted message.</p>
|
||||
%% <p><b>Note:</b> You need to use different Nonce values for different messages. Otherwise the same stream is produced and thus
|
||||
%% the messages will have predictability which in turn makes the encryption scheme fail.</p>
|
||||
%% @end
|
||||
-spec stream_chacha20(Len, Nonce, Key) -> CryptoStream
|
||||
when
|
||||
Len :: non_neg_integer(),
|
||||
Nonce :: binary(),
|
||||
Key :: binary(),
|
||||
CryptoStream :: binary().
|
||||
stream_chacha20(Len, Nonce, Key) when is_integer(Len), Len >= 0, Len =< ?STREAM_SIZE ->
|
||||
bump(enacl_nif:crypto_stream_chacha20_b(Len, Nonce, Key),
|
||||
?STREAM_REDUCTIONS,
|
||||
?STREAM_SIZE,
|
||||
Len);
|
||||
stream_chacha20(Len, Nonce, Key) when is_integer(Len), Len >= 0 ->
|
||||
enacl_nif:crypto_stream_chacha20(Len, Nonce, Key);
|
||||
stream_chacha20(_, _, _) -> error(badarg).
|
||||
|
||||
%% @doc stream_chacha20_xor/3 encrypts a plaintext message into ciphertext
|
||||
%%
|
||||
%% The stream_chacha20_xor/3 function works by using the {@link stream_chacha20/3} api to XOR a message with the cryptographic stream. The same
|
||||
%% caveat applies: the nonce must be new for each sent message or the system fails to work.
|
||||
%% @end
|
||||
-spec stream_chacha20_xor(Msg, Nonce, Key) -> CipherText
|
||||
when
|
||||
Msg :: iodata(),
|
||||
Nonce :: binary(),
|
||||
Key :: binary(),
|
||||
CipherText :: binary().
|
||||
stream_chacha20_xor(Msg, Nonce, Key) ->
|
||||
case iolist_size(Msg) of
|
||||
K when K =< ?STREAM_SIZE ->
|
||||
bump(enacl_nif:crypto_stream_chacha20_xor_b(Msg, Nonce, Key),
|
||||
?STREAM_REDUCTIONS,
|
||||
?STREAM_SIZE,
|
||||
K);
|
||||
_ ->
|
||||
enacl_nif:crypto_stream_chacha20_xor(Msg, Nonce, Key)
|
||||
end.
|
||||
|
||||
%% @doc auth_key_size/0 returns the byte-size of the authentication key
|
||||
%% @end
|
||||
%% @doc stream_nonce_size/0 returns the byte size of the nonce for streams
|
||||
%% @end
|
||||
-spec stream_nonce_size() -> pos_integer().
|
||||
|
@ -52,6 +52,14 @@
|
||||
crypto_secretbox_open/3,
|
||||
crypto_secretbox_open_b/3,
|
||||
|
||||
crypto_stream_chacha20_KEYBYTES/0,
|
||||
crypto_stream_chacha20_NONCEBYTES/0,
|
||||
|
||||
crypto_stream_chacha20/3,
|
||||
crypto_stream_chacha20_b/3,
|
||||
crypto_stream_chacha20_xor/3,
|
||||
crypto_stream_chacha20_xor_b/3,
|
||||
|
||||
crypto_stream_KEYBYTES/0,
|
||||
crypto_stream_NONCEBYTES/0,
|
||||
|
||||
@ -168,6 +176,13 @@ crypto_secretbox_b(_Msg, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
||||
crypto_secretbox_open(_Msg, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
||||
crypto_secretbox_open_b(_Msg, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
||||
|
||||
crypto_stream_chacha20_KEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
||||
crypto_stream_chacha20_NONCEBYTES() -> erlang:nif_error(nif_not_loaded).
|
||||
crypto_stream_chacha20(_Bytes, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
||||
crypto_stream_chacha20_b(_Bytes, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
||||
crypto_stream_chacha20_xor(_M, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
||||
crypto_stream_chacha20_xor_b(_M, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
||||
|
||||
crypto_stream_KEYBYTES() -> erlang:nif_error(nif_not_loaded).
|
||||
crypto_stream_NONCEBYTES() -> erlang:nif_error(nif_not_loaded).
|
||||
crypto_stream(_Bytes, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
|
||||
|
Loading…
x
Reference in New Issue
Block a user