1
0
forked from QPQ-AG/enoise

WIP: Reorientation

This commit is contained in:
2026-06-12 11:02:47 +09:00
parent a5da9d08f5
commit d7c8f1ec29
25 changed files with 361 additions and 364 deletions
+1
View File
@@ -0,0 +1 @@
{"src/*", [debug_info, {i, "include/"}, {outdir, "ebin/"}]}.
+7 -8
View File
@@ -1,15 +1,14 @@
ISC License
Copyright (c) 2018, aeternity developers
Copyright 2026 Craig Everett <craigeverett@qpq.swiss>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
THE SOFTWARE IS PROVIDED AS IS AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
+4 -20
View File
@@ -1,17 +1,17 @@
enoise
zNoise
=====
An Erlang implementation of the [Noise protocol](https://noiseprotocol.org/)
`enoise` provides a generic handshake mechanism, that can be used in a couple
of different ways. There is also a plain `gen_tcp`-wrapper, where you can
`zNoise` provides a generic handshake mechanism, that can be used in a couple
of different ways. There is also a plain `gen_tcp` wrapper, where you can
"upgrade" a TCP socket to a Noise socket and use it in much the same way as you
would use `gen_tcp`.
Interactive handshake
---------------------
When using `enoise` to do an interactive handshake, `enoise` will only take
When using `zNoise` to do an interactive handshake, `zNoise` will only take
care of message composition/decompositiona and encryption/decryption - i.e. the
user has to do the actual sending and receiving.
@@ -29,19 +29,3 @@ RX channel and a TX channel respectively.
The provided `gen_tcp`-wrapper is implemented using the generic handshake, see
`src/enoise.erl`.
Build
-----
$ rebar3 compile
Test
----
$ rebar3 eunit
Typecheck
---------
$ rebar3 dialyzer
$ elp --eqwalize-all --rebar
-14
View File
@@ -1,14 +0,0 @@
{erl_opts, [debug_info]}.
{plugins, [rebar3_hex]}.
{profiles, [{test, [{deps, [ {jsx, {git, "https://github.com/talentdeficit/jsx.git", {tag, "2.8.0"}}}
, {eqwalizer_support, {git_subdir, "https://github.com/whatsapp/eqwalizer.git", {branch, "main"}, "eqwalizer_support"}}
]}
]}
]}.
{xref_checks, [undefined_function_calls, undefined_functions,
locals_not_used,
deprecated_function_calls, deprecated_functions]}.
{dialyzer, [{warnings, [unknown]}]}.
-1
View File
@@ -1 +0,0 @@
[].
-15
View File
@@ -1,15 +0,0 @@
{application, enoise,
[{description, "An Erlang implementation of the Noise protocol"},
{vsn, "1.2.0"},
{registered, []},
{applications,
[kernel,
stdlib,
crypto
]},
{env,[]},
{modules, []},
{maintainers, ["Hans Svensson"]},
{licenses, ["ISC"]},
{links, [{"Github", "https://github.com/aeternity/enoise"}]}
]}.
+42 -38
View File
@@ -2,14 +2,18 @@
%%% @copyright 2018, Aeternity Anstalt
%%%
%%% @doc
%%% Interface to the [Noise protocol](https://noiseprotocol.org)
%%% Interface to the Noise protocol: https://noiseprotocol.org
%%%
%%% For convenience there is also an API to use Noise over TCP (i.e. `gen_tcp')
%%% and after "upgrading" a `gen_tcp'-socket into a `enoise'-socket it has a
%%% and after "upgrading" a `gen_tcp'-socket into a `znoise'-socket it has a
%%% similar API as `gen_tcp'.
%%% @end
-module(enoise).
-module(znoise).
-vsn("0.1.0").
-author("Craig Everett <craigeverett@qpq.swiss>").
-copyright("QPQ AG <info@qpq.swiss>").
-license("ISC").
%% Main function with generic Noise handshake
-export([handshake/2, handshake/3, step_handshake/2]).
@@ -22,10 +26,10 @@
send/2,
set_active/2]).
-record(enoise, {pid}).
-record(znoise, {pid}).
-type key() :: binary().
-type keypair() :: enoise_keypair:keypair().
-type keypair() :: znoise_keypair:keypair().
-type options() :: [option()].
%% A list of Noise options is a proplist, it *must* contain a value `noise'
@@ -42,7 +46,7 @@
| {prologue, binary()} %% Optional
| {timeout, integer() | infinity}. %% Optional
-type protocol_option() :: enoise_protocol:protocol()
-type protocol_option() :: znoise_protocol:protocol()
| string()
| binary().
%% Either an instantiated Noise protocol configuration or the name of a Noise
@@ -64,12 +68,12 @@
%% Noise communication state - used to parameterize a handshake. Consists of a
%% send function, one receive function, and an internal state.
-type split_state() :: enoise_hs_state:noise_split_state().
-type split_state() :: znoise_hs_state:noise_split_state().
%% Return value from the final `split' operation. Provides a CipherState for
%% receiving and a CipherState transmission. Also includes the final handshake
%% hash for channel binding.
-opaque socket() :: #enoise{}.
-opaque socket() :: #znoise{}.
%% An abstract Noise socket - holds a reference to a socket that has completed
%% a Noise handshake.
@@ -81,8 +85,8 @@
-spec handshake(Options, Role) -> Outcome
when Options :: options(),
Role :: enoise_hs_state:noise_role(),
Outcome :: {ok, enoise_hs_state:state()}
Role :: znoise_hs_state:noise_role(),
Outcome :: {ok, znoise_hs_state:state()}
| {error, term()}.
%% @doc
%% Start an interactive handshake
@@ -93,7 +97,7 @@ handshake(Options, Role) ->
-spec handshake(Options, Role, ComState) -> Outcome
when Options :: options(),
Role :: enoise_hs_state:noise_role(),
Role :: znoise_hs_state:noise_role(),
ComState :: com_state(),
Outcome :: {ok, split_state(), com_state()}
| {error, term()}.
@@ -111,11 +115,11 @@ handshake(Options, Role, ComState) ->
-spec step_handshake(HState, Data) -> Next
when HState :: enoise_hs_state:state(),
when HState :: znoise_hs_state:state(),
Data :: {rcvd, binary()}
| {send, binary()},
Next :: {ok, send, binary(), enoise_hs_state:state()}
| {ok, rcvd, binary(), enoise_hs_state:state()}
Next :: {ok, send, binary(), znoise_hs_state:state()}
| {ok, rcvd, binary(), znoise_hs_state:state()}
| {ok, done, split_state()}
| {error, term()}.
%% @doc
@@ -128,7 +132,7 @@ step_handshake(HState, Data) ->
-spec connect(TcpSock, Options) -> Outcome
when TcpSock :: gen_tcp:socket(),
Options :: options(),
Outcome :: {ok, socket(), enoise_hs_state:state()}
Outcome :: {ok, socket(), znoise_hs_state:state()}
| {error, term()}.
%% @doc
%% Upgrades a gen_tcp, or equivalent, connected socket to a Noise socket,
@@ -146,7 +150,7 @@ connect(TcpSock, Options) ->
-spec accept(TcpSock, Options) -> Outcome
when TcpSock :: gen_tcp:socket(),
Options :: options(),
Outcome :: {ok, socket(), enoise_hs_state:state()}
Outcome :: {ok, socket(), znoise_hs_state:state()}
| {error, term()}.
%% @doc
%% Upgrades a gen_tcp, or equivalent, connected socket to a Noise socket,
@@ -168,8 +172,8 @@ accept(TcpSock, Options) ->
%% @doc
%% Writes `Data' to `Socket'
send(#enoise{ pid = Pid }, Data) ->
enoise_connection:send(Pid, Data).
send(#znoise{ pid = Pid }, Data) ->
znoise_tcp:send(Pid, Data).
-spec close(NoiseSock) -> Outcome
@@ -178,8 +182,8 @@ send(#enoise{ pid = Pid }, Data) ->
%% @doc
%% Closes a Noise connection.
close(#enoise{ pid = Pid }) ->
enoise_connection:close(Pid).
close(#znoise{ pid = Pid }) ->
znoise_tcp:close(Pid).
-spec controlling_process(Socket, Pid) -> Outcome
@@ -191,8 +195,8 @@ close(#enoise{ pid = Pid }) ->
%% process is the owner of an Noise socket, and receives all messages from the
%% socket.
controlling_process(#enoise{ pid = Pid }, NewPid) ->
enoise_connection:controlling_process(Pid, NewPid).
controlling_process(#znoise{ pid = Pid }, NewPid) ->
znoise_tcp:controlling_process(Pid, NewPid).
-spec set_active(Socket, Mode) -> Outcome
@@ -203,19 +207,19 @@ controlling_process(#enoise{ pid = Pid }, NewPid) ->
%% Set the active option `true | once'. Note that `N' and `false' are
%% not valid options for a Noise socket.
set_active(#enoise{ pid = Pid }, ActiveMode) ->
enoise_connection:set_active(Pid, ActiveMode).
set_active(#znoise{ pid = Pid }, ActiveMode) ->
znoise_tcp:set_active(Pid, ActiveMode).
%%% Internal functions
do_handshake(HState, ComState, Timeout) ->
case enoise_hs_state:next_message(HState) of
case znoise_hs_state:next_message(HState) of
in ->
case hs_recv_msg(ComState, Timeout) of
{ok, Data, ComState1} ->
case enoise_hs_state:read_message(HState, Data) of
case znoise_hs_state:read_message(HState, Data) of
{ok, HState1, _Msg} ->
do_handshake(HState1, ComState1, Timeout);
Err = {error, _} ->
@@ -225,7 +229,7 @@ do_handshake(HState, ComState, Timeout) ->
Err
end;
out ->
{ok, HState1, Msg} = enoise_hs_state:write_message(HState, <<>>),
{ok, HState1, Msg} = znoise_hs_state:write_message(HState, <<>>),
case hs_send_msg(ComState, Msg) of
{ok, ComState1} ->
do_handshake(HState1, ComState1, Timeout);
@@ -233,7 +237,7 @@ do_handshake(HState, ComState, Timeout) ->
Err
end;
done ->
{ok, Res} = enoise_hs_state:finalize(HState),
{ok, Res} = znoise_hs_state:finalize(HState),
{ok, Res, ComState}
end.
@@ -250,19 +254,19 @@ hs_send_msg(CS = #{ send_msg := Send, state := S }, Data) ->
end.
do_step_handshake(HState, Data) ->
case {enoise_hs_state:next_message(HState), Data} of
case {znoise_hs_state:next_message(HState), Data} of
{in, {rcvd, Encrypted}} ->
case enoise_hs_state:read_message(HState, Encrypted) of
case znoise_hs_state:read_message(HState, Encrypted) of
{ok, HState1, Msg} ->
{ok, rcvd, Msg, HState1};
Err = {error, _} ->
Err
end;
{out, {send, Payload}} ->
{ok, HState1, Msg} = enoise_hs_state:write_message(HState, Payload),
{ok, HState1, Msg} = znoise_hs_state:write_message(HState, Payload),
{ok, send, Msg, HState1};
{done, done} ->
{ok, Res} = enoise_hs_state:finalize(HState),
{ok, Res} = znoise_hs_state:finalize(HState),
{ok, done, Res};
{Next, _} ->
{error, {invalid_step, expected, Next, got, Data}}
@@ -289,8 +293,8 @@ do_tcp_handshake(Options, Role, TcpSock, Active) ->
state => {TcpSock, Active, <<>>}},
case handshake(Options, Role, ComState) of
{ok, #{rx := Rx, tx := Tx, final_state := FState}, #{state := {_, _, Buf}}} ->
case enoise_connection:start_link(TcpSock, Rx, Tx, self(), {Active, Buf}) of
{ok, Pid} -> {ok, #enoise{ pid = Pid }, FState};
case znoise_tcp:start_link(TcpSock, Rx, Tx, self(), {Active, Buf}) of
{ok, Pid} -> {ok, #znoise{ pid = Pid }, FState};
Error -> Error
end;
Error ->
@@ -303,15 +307,15 @@ create_hstate(Options, Role) ->
Noise = proplists:get_value(noise, Options),
Protocol =
case is_binary(Noise) orelse is_list(Noise) of
true -> enoise_protocol:from_name(X);
true -> znoise_protocol:from_name(X);
false -> Noise
end,
DH = enoise_protocol:dh(Protocol),
DH = znoise_protocol:dh(Protocol),
S = proplists:get_value(s, Options, undefined),
E = proplists:get_value(e, Options, undefined),
RS = remote_keypair(DH, proplists:get_value(rs, Options, undefined)),
RE = remote_keypair(DH, proplists:get_value(re, Options, undefined)),
enoise_hs_state:init(Protocol, Role, Prologue, {S, E, RS, RE}).
znoise_hs_state:init(Protocol, Role, Prologue, {S, E, RS, RE}).
check_gen_tcp(TcpSock) ->
@@ -366,4 +370,4 @@ gen_tcp_rcv_msg({TcpSock, Active, Buf}, Timeout) ->
remote_keypair(_DH, undefined) ->
undefined;
remote_keypair(DH, RemotePub) when is_binary(RemotePub) ->
enoise_keypair:new(DH, RemotePub).
znoise_keypair:new(DH, RemotePub).
@@ -1,12 +1,15 @@
%%% ------------------------------------------------------------------
%%% @copyright 2026, QPQ AG
%%% @copyright 2018, Aeternity Anstalt
%%%
%%% @doc Module encapsulating a Noise Cipher state
%%%
%%% @doc
%%% Module encapsulating a Noise Cipher state
%%% @end
%%% ------------------------------------------------------------------
-module(enoise_cipher_state).
-module(znoise_cipher_state).
-vsn("0.1.0").
-author("Craig Everett <craigeverett@qpq.swiss>").
-copyright("QPQ AG <info@qpq.swiss>").
-license("ISC").
-export([ cipher/1
, decrypt_with_ad/3
@@ -19,7 +22,7 @@
, set_nonce/2
]).
-include("enoise.hrl").
-include("znoise.hrl").
-type noise_cipher() :: 'ChaChaPoly' | 'AESGCM'.
-type nonce() :: non_neg_integer().
@@ -54,7 +57,7 @@ set_nonce(CState = #noise_cs{}, Nonce) ->
encrypt_with_ad(CState = #noise_cs{ k = empty }, _AD, PlainText) ->
{ok, CState, PlainText};
encrypt_with_ad(CState = #noise_cs{ k = K, n = N, cipher = Cipher }, AD, PlainText) ->
CipherText = enoise_crypto:encrypt(Cipher, K, N, AD, PlainText),
CipherText = znoise_crypto:encrypt(Cipher, K, N, AD, PlainText),
{ok, CState#noise_cs{ n = N+1 }, CipherText}.
-spec decrypt_with_ad(CState :: state(), AD :: binary(), CipherText :: binary()) ->
@@ -62,7 +65,7 @@ encrypt_with_ad(CState = #noise_cs{ k = K, n = N, cipher = Cipher }, AD, PlainTe
decrypt_with_ad(CState = #noise_cs{ k = empty }, _AD, CipherText) ->
{ok, CState, CipherText};
decrypt_with_ad(CState = #noise_cs{ k = K, n = N, cipher = Cipher }, AD, CipherText) ->
case enoise_crypto:decrypt(Cipher, K, N, AD, CipherText) of
case znoise_crypto:decrypt(Cipher, K, N, AD, CipherText) of
PlainText when is_binary(PlainText) ->
{ok, CState#noise_cs{ n = N+1 }, PlainText};
Err = {error, _} ->
@@ -73,7 +76,7 @@ decrypt_with_ad(CState = #noise_cs{ k = K, n = N, cipher = Cipher }, AD, CipherT
rekey(CState = #noise_cs{ k = empty }) ->
CState;
rekey(CState = #noise_cs{ k = K, cipher = Cipher }) ->
CState#noise_cs{ k = enoise_crypto:rekey(Cipher, K) }.
CState#noise_cs{ k = znoise_crypto:rekey(Cipher, K) }.
-spec cipher(CState :: state()) -> noise_cipher().
cipher(#noise_cs{ cipher = Cipher }) ->
+21 -18
View File
@@ -1,14 +1,17 @@
%%% ------------------------------------------------------------------
%%% @copyright 2026, QPQ AG
%%% @copyright 2018, Aeternity Anstalt
%%%
%%% @doc Module implementing crypto primitives needed by Noise protocol
%%%
%%% @doc
%%% Module implementing crypto primitives needed by Noise protocol
%%% @end
%%% ------------------------------------------------------------------
-module(enoise_crypto).
-module(znoise_crypto).
-vsn("0.1.0").
-author("Craig Everett <craigeverett@qpq.swiss>").
-copyright("QPQ AG <info@qpq.swiss>").
-license("ISC").
-include("enoise.hrl").
-include("znoise.hrl").
-export([ decrypt/5
, dh/3
@@ -24,14 +27,14 @@
-define(MAC_LEN, 16).
-type keypair() :: enoise_keypair:keypair().
-type keypair() :: znoise_keypair:keypair().
%% @doc Perform a Diffie-Hellman calculation with the secret key from `Key1'
%% and the public key from `Key2' with algorithm `Algo'.
-spec dh(Algo :: enoise_hs_state:noise_dh(),
-spec dh(Algo :: znoise_hs_state:noise_dh(),
Key1:: keypair(), Key2 :: keypair()) -> binary().
dh(Type, Key1, Key2) when Type == dh25519; Type == dh448 ->
dh_(ecdh_type(Type), enoise_keypair:pubkey(Key2), enoise_keypair:seckey(Key1));
dh_(ecdh_type(Type), znoise_keypair:pubkey(Key2), znoise_keypair:seckey(Key1));
dh(Type, _Key1, _Key2) ->
error({unsupported_diffie_hellman, Type}).
@@ -41,7 +44,7 @@ ecdh_type(dh448) -> x448.
dh_(DHType, OtherPub, MyPriv) ->
crypto:compute_key(ecdh, OtherPub, MyPriv, DHType).
-spec hmac(Hash :: enoise_sym_state:noise_hash(),
-spec hmac(Hash :: znoise_sym_state:noise_hash(),
Key :: binary(), Data :: binary()) -> binary().
hmac(Hash, Key, Data) ->
BLen = blocklen(Hash),
@@ -50,7 +53,7 @@ hmac(Hash, Key, Data) ->
Block2 = hmac_format_key(Hash, Key, 16#5C, BLen),
hash(Hash, <<Block2/binary, Hash1/binary>>).
-spec hkdf(Hash :: enoise_sym_state:noise_hash(),
-spec hkdf(Hash :: znoise_sym_state:noise_hash(),
Key :: binary(), Data :: binary()) -> [binary()].
hkdf(Hash, Key, Data) ->
TempKey = hmac(Hash, Key, Data),
@@ -59,7 +62,7 @@ hkdf(Hash, Key, Data) ->
Output3 = hmac(Hash, TempKey, <<Output2/binary, 3:8>>),
[Output1, Output2, Output3].
-spec rekey(Cipher :: enoise_cipher_state:noise_cipher(), Key :: binary()) -> binary().
-spec rekey(Cipher :: znoise_cipher_state:noise_cipher(), Key :: binary()) -> binary().
rekey('ChaChaPoly', K0) ->
KLen = 32,
<<K:KLen/binary, _/binary>> = encrypt('ChaChaPoly', K0, ?MAX_NONCE, <<>>, <<0:(32*8)>>),
@@ -67,13 +70,13 @@ rekey('ChaChaPoly', K0) ->
rekey(Cipher, K) ->
encrypt(Cipher, K, ?MAX_NONCE, <<>>, <<0:(32*8)>>).
-spec encrypt(Cipher :: enoise_cipher_state:noise_cipher(), Key :: binary(),
-spec encrypt(Cipher :: znoise_cipher_state:noise_cipher(), Key :: binary(),
Nonce :: non_neg_integer(), Ad :: binary(), PlainText :: binary()) -> binary().
encrypt(Cipher, K, N, Ad, PlainText) ->
{CText, CTag} = crypto:crypto_one_time_aead(cipher(Cipher), K, nonce(Cipher, N), PlainText, Ad, true),
<<CText/binary, CTag/binary>>.
-spec decrypt(Cipher ::enoise_cipher_state:noise_cipher(), Key :: binary(),
-spec decrypt(Cipher ::znoise_cipher_state:noise_cipher(), Key :: binary(),
Nonce :: non_neg_integer(), AD :: binary(),
CipherText :: binary()) -> binary() | {error, term()}.
decrypt(Cipher, K, N, Ad, CipherText0) ->
@@ -90,7 +93,7 @@ nonce('AESGCM', N) -> <<0:32, N:64/big-unsigned-integer>>.
cipher('ChaChaPoly') -> chacha20_poly1305;
cipher('AESGCM') -> aes_256_gcm.
-spec hash(Hash :: enoise_sym_state:noise_hash(), Data :: binary()) -> binary().
-spec hash(Hash :: znoise_sym_state:noise_hash(), Data :: binary()) -> binary().
hash(blake2s, Data) ->
crypto:hash(blake2s, Data);
hash(blake2b, Data) ->
@@ -113,19 +116,19 @@ pad(Data, MinSize, PadByte) ->
<<Data/binary, PadData/binary>>
end.
-spec hashlen(Hash :: enoise_sym_state:noise_hash()) -> non_neg_integer().
-spec hashlen(Hash :: znoise_sym_state:noise_hash()) -> non_neg_integer().
hashlen(sha256) -> 32;
hashlen(sha512) -> 64;
hashlen(blake2s) -> 32;
hashlen(blake2b) -> 64.
-spec blocklen(Hash :: enoise_sym_state:noise_hash()) -> non_neg_integer().
-spec blocklen(Hash :: znoise_sym_state:noise_hash()) -> non_neg_integer().
blocklen(sha256) -> 64;
blocklen(sha512) -> 128;
blocklen(blake2s) -> 64;
blocklen(blake2b) -> 128.
-spec dhlen(DH :: enoise_hs_state:noise_dh()) -> non_neg_integer().
-spec dhlen(DH :: znoise_hs_state:noise_dh()) -> non_neg_integer().
dhlen(dh25519) -> 32;
dhlen(dh448) -> 56.
@@ -5,7 +5,11 @@
%%% Module encapsulating a Noise handshake state
%%% @end
-module(enoise_hs_state).
-module(znoise_hs_state).
-vsn("0.1.0").
-author("Craig Everett <craigeverett@qpq.swiss>").
-copyright("QPQ AG <info@qpq.swiss>").
-license("ISC").
-export([finalize/1,
init/4,
@@ -14,61 +18,61 @@
remote_keys/1,
write_message/2]).
-include("enoise.hrl").
-include("znoise.hrl").
-type noise_role() :: initiator | responder.
-type noise_dh() :: dh25519 | dh448.
-type noise_token() :: s | e | ee | ss | es | se.
-type keypair() :: enoise_keypair:keypair().
-type noise_split_state() :: #{rx := enoise_cipher_state:state(),
tx := enoise_cipher_state:state(),
-type keypair() :: znoise_keypair:keypair().
-type noise_split_state() :: #{rx := znoise_cipher_state:state(),
tx := znoise_cipher_state:state(),
hs_hash := binary(),
final_state => state() }.
-type optional_key() :: undefined | keypair().
-type initial_keys() :: {optional_key(), optional_key(), optional_key(), optional_key()}.
-record(noise_hs, { ss :: enoise_sym_state:state()
-record(noise_hs, { ss :: znoise_sym_state:state()
, s :: keypair() | undefined
, e :: keypair() | undefined
, rs :: keypair() | undefined
, re :: keypair() | undefined
, role = initiator :: noise_role()
, dh = dh25519 :: noise_dh()
, msgs = [] :: [enoise_protocol:noise_msg()] }).
, msgs = [] :: [znoise_protocol:noise_msg()] }).
-opaque state() :: #noise_hs{}.
-export_type([noise_dh/0, noise_role/0, noise_split_state/0, noise_token/0, state/0]).
-spec init(Protocol :: enoise_protocol:protocol(), Role :: noise_role(),
-spec init(Protocol :: znoise_protocol:protocol(), Role :: noise_role(),
Prologue :: binary(), Keys :: initial_keys()) -> {ok, state()} | {error, term()}.
init(Protocol, Role, Prologue, {S, E, RS, RE}) ->
SS0 = enoise_sym_state:init(Protocol),
SS1 = enoise_sym_state:mix_hash(SS0, Prologue),
SS0 = znoise_sym_state:init(Protocol),
SS1 = znoise_sym_state:mix_hash(SS0, Prologue),
HS = #noise_hs{ ss = SS1
, s = S, e = E, rs = RS, re = RE
, role = Role
, dh = enoise_protocol:dh(Protocol)
, msgs = enoise_protocol:msgs(Role, Protocol) },
PreMsgs = enoise_protocol:pre_msgs(Role, Protocol),
, dh = znoise_protocol:dh(Protocol)
, msgs = znoise_protocol:msgs(Role, Protocol) },
PreMsgs = znoise_protocol:pre_msgs(Role, Protocol),
pre_mix(PreMsgs, HS).
pre_mix([], HS) -> {ok, HS};
pre_mix([{out, [s]} | Msgs], HS = #noise_hs{ s = S }) when S /= undefined ->
pre_mix(Msgs, mix_hash(HS, enoise_keypair:pubkey(S)));
pre_mix(Msgs, mix_hash(HS, znoise_keypair:pubkey(S)));
pre_mix([{out, [e]} | Msgs], HS = #noise_hs{ e = E }) when E /= undefined ->
pre_mix(Msgs, mix_hash(HS, enoise_keypair:pubkey(E)));
pre_mix(Msgs, mix_hash(HS, znoise_keypair:pubkey(E)));
pre_mix([{in, [s]} | Msgs], HS = #noise_hs{ rs = RS }) when RS /= undefined ->
pre_mix(Msgs, mix_hash(HS, enoise_keypair:pubkey(RS)));
pre_mix(Msgs, mix_hash(HS, znoise_keypair:pubkey(RS)));
pre_mix([{in, [e]} | Msgs], HS = #noise_hs{ re = RE }) when RE /= undefined ->
pre_mix(Msgs, mix_hash(HS, enoise_keypair:pubkey(RE)));
pre_mix(Msgs, mix_hash(HS, znoise_keypair:pubkey(RE)));
pre_mix(_Msg, _HS) ->
{error, invalid_noise_setup}.
-spec finalize(HS :: state()) -> {ok, noise_split_state()} | {error, term()}.
finalize(HS = #noise_hs{ msgs = [], ss = SS, role = Role }) ->
{C1, C2} = enoise_sym_state:split(SS),
HSHash = enoise_sym_state:h(SS),
{C1, C2} = znoise_sym_state:split(SS),
HSHash = znoise_sym_state:h(SS),
Final = #{ hs_hash => HSHash, final_state => HS },
case Role of
initiator -> {ok, Final#{ tx => C1, rx => C2 }};
@@ -116,38 +120,38 @@ read_message(HS, [Token | Tokens], Data0) ->
write_token(HS = #noise_hs{ e = undefined }, e) ->
E = new_key_pair(HS),
PubE = enoise_keypair:pubkey(E),
PubE = znoise_keypair:pubkey(E),
{mix_hash(HS#noise_hs{ e = E }, PubE), PubE};
%% Should only apply during test - TODO: secure this
write_token(HS = #noise_hs{ e = E }, e) ->
PubE = enoise_keypair:pubkey(E),
PubE = znoise_keypair:pubkey(E),
{mix_hash(HS, PubE), PubE};
write_token(HS = #noise_hs{ s = S }, s) ->
{ok, HS1, Msg} = encrypt_and_hash(HS, enoise_keypair:pubkey(S)),
{ok, HS1, Msg} = encrypt_and_hash(HS, znoise_keypair:pubkey(S)),
{HS1, Msg};
write_token(HS, Token) ->
{K1, K2} = dh_token(HS, Token),
{mix_key(HS, dh(HS, K1, K2)), <<>>}.
read_token(HS = #noise_hs{ re = undefined, dh = DH }, e, Data0) ->
DHLen = enoise_crypto:dhlen(DH),
DHLen = znoise_crypto:dhlen(DH),
case Data0 of
<<REPub:DHLen/binary, Data1/binary>> ->
RE = enoise_keypair:new(DH, REPub),
RE = znoise_keypair:new(DH, REPub),
{ok, mix_hash(HS#noise_hs{ re = RE }, REPub), Data1};
_ ->
{error, {bad_data, {failed_to_read_token, e, DHLen}}}
end;
read_token(HS = #noise_hs{ rs = undefined, dh = DH }, s, Data0) ->
DHLen = case has_key(HS) of
true -> enoise_crypto:dhlen(DH) + 16;
false -> enoise_crypto:dhlen(DH)
true -> znoise_crypto:dhlen(DH) + 16;
false -> znoise_crypto:dhlen(DH)
end,
case Data0 of
<<Temp:DHLen/binary, Data1/binary>> ->
case decrypt_and_hash(HS, Temp) of
{ok, HS1, RSPub} ->
RS = enoise_keypair:new(DH, RSPub),
RS = znoise_keypair:new(DH, RSPub),
{ok, HS1#noise_hs{ rs = RS }, Data1};
Err = {error, _} ->
Err
@@ -168,27 +172,27 @@ dh_token(#noise_hs{ s = S, rs = RS } , ss) -> {S, RS}.
%% Local wrappers
new_key_pair(#noise_hs{ dh = DH }) ->
enoise_keypair:new(DH).
znoise_keypair:new(DH).
dh(#noise_hs{ dh = DH }, Key1, Key2) ->
enoise_crypto:dh(DH, Key1, Key2).
znoise_crypto:dh(DH, Key1, Key2).
has_key(#noise_hs{ ss = SS }) ->
CS = enoise_sym_state:cipher_state(SS),
enoise_cipher_state:has_key(CS).
CS = znoise_sym_state:cipher_state(SS),
znoise_cipher_state:has_key(CS).
mix_key(HS = #noise_hs{ ss = SS0 }, Data) ->
HS#noise_hs{ ss = enoise_sym_state:mix_key(SS0, Data) }.
HS#noise_hs{ ss = znoise_sym_state:mix_key(SS0, Data) }.
mix_hash(HS = #noise_hs{ ss = SS0 }, Data) ->
HS#noise_hs{ ss = enoise_sym_state:mix_hash(SS0, Data) }.
HS#noise_hs{ ss = znoise_sym_state:mix_hash(SS0, Data) }.
encrypt_and_hash(HS = #noise_hs{ ss = SS0 }, PlainText) ->
{ok, SS1, CipherText} = enoise_sym_state:encrypt_and_hash(SS0, PlainText),
{ok, SS1, CipherText} = znoise_sym_state:encrypt_and_hash(SS0, PlainText),
{ok, HS#noise_hs{ ss = SS1 }, CipherText}.
decrypt_and_hash(HS = #noise_hs{ ss = SS0 }, CipherText) ->
case enoise_sym_state:decrypt_and_hash(SS0, CipherText) of
case znoise_sym_state:decrypt_and_hash(SS0, CipherText) of
{ok, SS1, PlainText} ->
{ok, HS#noise_hs{ ss = SS1 }, PlainText};
@@ -1,12 +1,15 @@
%%% ------------------------------------------------------------------
%%% @copyright 2026, QPQ AG
%%% @copyright 2018, Aeternity Anstalt
%%%
%%% @doc Module is an abstract data type for a key pair.
%%%
%%% @doc
%%% Module is an abstract data type for a key pair.
%%% @end
%%% ------------------------------------------------------------------
-module(enoise_keypair).
-module(znoise_keypair).
-vsn("0.1.0").
-author("Craig Everett <craigeverett@qpq.swiss>").
-copyright("QPQ AG <info@qpq.swiss>").
-license("ISC").
-export([ key_type/1
, new/1
@@ -1,12 +1,15 @@
%%% ------------------------------------------------------------------
%%% @copyright 2026, QPQ AG
%%% @copyright 2018, Aeternity Anstalt
%%%
%%% @doc Module defining Noise protocol configurations
%%%
%%% @doc
%%% Module defining Noise protocol configurations
%%% @end
%%% ------------------------------------------------------------------
-module(enoise_protocol).
-module(znoise_protocol).
-vsn("0.1.0").
-author("Craig Everett <craigeverett@qpq.swiss>").
-copyright("QPQ AG <info@qpq.swiss>").
-license("ISC").
-export([ cipher/1
, dh/1
@@ -23,28 +26,28 @@
-endif.
-type noise_pattern() :: nn | kn | nk | kk | nx | kx | xn | in | xk | ik | xx | ix.
-type noise_msg() :: {in | out, [enoise_hs_state:noise_token()]}.
-type noise_msg() :: {in | out, [znoise_hs_state:noise_token()]}.
-record(noise_protocol,
{ hs_pattern = noiseNN :: noise_pattern()
, dh = dh25519 :: enoise_hs_state:noise_dh()
, cipher = 'ChaChaPoly' :: enoise_cipher_state:noise_cipher()
, hash = blake2b :: enoise_sym_state:noise_hash()
, dh = dh25519 :: znoise_hs_state:noise_dh()
, cipher = 'ChaChaPoly' :: znoise_cipher_state:noise_cipher()
, hash = blake2b :: znoise_sym_state:noise_hash()
}).
-opaque protocol() :: #noise_protocol{}.
-export_type([noise_msg/0, noise_pattern/0, protocol/0]).
-spec cipher(Protocol :: protocol()) -> enoise_cipher_state:noise_cipher().
-spec cipher(Protocol :: protocol()) -> znoise_cipher_state:noise_cipher().
cipher(#noise_protocol{ cipher = Cipher }) ->
Cipher.
-spec dh(Protocol :: protocol()) -> enoise_hs_state:noise_dh().
-spec dh(Protocol :: protocol()) -> znoise_hs_state:noise_dh().
dh(#noise_protocol{ dh = Dh }) ->
Dh.
-spec hash(Protocol :: protocol()) -> enoise_sym_state:noise_hash().
-spec hash(Protocol :: protocol()) -> znoise_sym_state:noise_hash().
hash(#noise_protocol{ hash = Hash }) ->
Hash.
@@ -80,17 +83,17 @@ from_name(String) ->
error({name_not_recognized, String})
end.
-spec msgs(Role :: enoise_hs_state:noise_role(), Protocol :: protocol()) -> [noise_msg()].
-spec msgs(Role :: znoise_hs_state:noise_role(), Protocol :: protocol()) -> [noise_msg()].
msgs(Role, #noise_protocol{ hs_pattern = Pattern }) ->
{_Pre, Msgs} = protocol(Pattern),
role_adapt(Role, Msgs).
-spec pre_msgs(Role :: enoise_hs_state:noise_role(), Protocol :: protocol()) -> [noise_msg()].
-spec pre_msgs(Role :: znoise_hs_state:noise_role(), Protocol :: protocol()) -> [noise_msg()].
pre_msgs(Role, #noise_protocol{ hs_pattern = Pattern }) ->
{PreMsgs, _Msgs} = protocol(Pattern),
role_adapt(Role, PreMsgs).
-spec role_adapt(Role :: enoise_hs_state:noise_role(), [noise_msg()]) -> [noise_msg()].
-spec role_adapt(Role :: znoise_hs_state:noise_role(), [noise_msg()]) -> [noise_msg()].
role_adapt(initiator, Msgs) ->
Msgs;
role_adapt(responder, Msgs) ->
@@ -1,12 +1,14 @@
%%% ------------------------------------------------------------------
%%% @copyright 2018, Aeternity Anstalt
%%%
%%% @doc Module encapsulating a Noise symmetric (hash) state
%%%
%%% @doc
%%% Module encapsulating a Noise symmetric (hash) state
%%% @end
%%% ------------------------------------------------------------------
-module(enoise_sym_state).
-module(znoise_sym_state).
-vsn("0.1.0").
-author("Craig Everett <craigeverett@qpq.swiss>").
-copyright("QPQ AG <info@qpq.swiss>").
-license("ISC").
-export([ cipher_state/1
, ck/1
@@ -21,11 +23,11 @@
, split/1
]).
-include("enoise.hrl").
-include("znoise.hrl").
-type noise_hash() :: sha256 | sha512 | blake2s | blake2b.
-record(noise_ss, { cs :: enoise_cipher_state:state()
-record(noise_ss, { cs :: znoise_cipher_state:state()
, ck = <<>> :: binary()
, h = <<>> :: binary()
, hash = blake2b :: noise_hash() }).
@@ -33,64 +35,64 @@
-opaque state() :: #noise_ss{}.
-export_type([noise_hash/0, state/0]).
-spec init(Protocol :: enoise_protocol:protocol()) -> state().
-spec init(Protocol :: znoise_protocol:protocol()) -> state().
init(Protocol) ->
Hash = enoise_protocol:hash(Protocol),
Cipher = enoise_protocol:cipher(Protocol),
Name = enoise_protocol:to_name(Protocol),
HashLen = enoise_crypto:hashlen(Hash),
Hash = znoise_protocol:hash(Protocol),
Cipher = znoise_protocol:cipher(Protocol),
Name = znoise_protocol:to_name(Protocol),
HashLen = znoise_crypto:hashlen(Hash),
H1 =
case byte_size(Name) > HashLen of
true -> enoise_crypto:hash(Hash, Name);
false -> enoise_crypto:pad(Name, HashLen, 16#00)
true -> znoise_crypto:hash(Hash, Name);
false -> znoise_crypto:pad(Name, HashLen, 16#00)
end,
#noise_ss{ h = H1
, ck = H1
, hash = Hash
, cs = enoise_cipher_state:init(empty, Cipher) }.
, cs = znoise_cipher_state:init(empty, Cipher) }.
-spec mix_key(SState :: state(), InputKeyMaterial :: binary()) -> state().
mix_key(SState = #noise_ss{ hash = Hash, ck = CK0, cs = CS0 }, InputKeyMaterial) ->
[CK1, <<TempK:32/binary, _/binary>> | _] =
enoise_crypto:hkdf(Hash, CK0, InputKeyMaterial),
CS1 = enoise_cipher_state:set_key(CS0, TempK),
znoise_crypto:hkdf(Hash, CK0, InputKeyMaterial),
CS1 = znoise_cipher_state:set_key(CS0, TempK),
SState#noise_ss{ ck = CK1, cs = CS1 }.
-spec mix_hash(SState :: state(), Data :: binary()) -> state().
mix_hash(SState = #noise_ss{ hash = Hash, h = H0 }, Data) ->
H1 = enoise_crypto:hash(Hash, <<H0/binary, Data/binary>>),
H1 = znoise_crypto:hash(Hash, <<H0/binary, Data/binary>>),
SState#noise_ss{ h = H1 }.
-spec mix_key_and_hash(SState :: state(), InputKeyMaterial :: binary()) -> state().
mix_key_and_hash(SState = #noise_ss{ hash = Hash, ck = CK0, cs = CS0 }, InputKeyMaterial) ->
[CK1, TempH, <<TempK:32/binary, _/binary>>] =
enoise_crypto:hkdf(Hash, CK0, InputKeyMaterial),
CS1 = enoise_cipher_state:set_key(CS0, TempK),
znoise_crypto:hkdf(Hash, CK0, InputKeyMaterial),
CS1 = znoise_cipher_state:set_key(CS0, TempK),
mix_hash(SState#noise_ss{ ck = CK1, cs = CS1 }, TempH).
-spec encrypt_and_hash(SState :: state(), PlainText :: binary()) -> {ok, state(), binary()}.
encrypt_and_hash(SState = #noise_ss{ cs = CS0, h = H }, PlainText) ->
{ok, CS1, CipherText} = enoise_cipher_state:encrypt_with_ad(CS0, H, PlainText),
{ok, CS1, CipherText} = znoise_cipher_state:encrypt_with_ad(CS0, H, PlainText),
{ok, mix_hash(SState#noise_ss{ cs = CS1 }, CipherText), CipherText}.
-spec decrypt_and_hash(SState :: state(), CipherText :: binary()) ->
{ok, state(), binary()} | {error, term()}.
decrypt_and_hash(SState = #noise_ss{ cs = CS0, h = H }, CipherText) ->
case enoise_cipher_state:decrypt_with_ad(CS0, H, CipherText) of
case znoise_cipher_state:decrypt_with_ad(CS0, H, CipherText) of
Err = {error, _} ->
Err;
{ok, CS1, PlainText} ->
{ok, mix_hash(SState#noise_ss{ cs = CS1 }, CipherText), PlainText}
end.
-spec split(SState :: state()) -> {enoise_cipher_state:state(), enoise_cipher_state:state()}.
-spec split(SState :: state()) -> {znoise_cipher_state:state(), znoise_cipher_state:state()}.
split(#noise_ss{ hash = Hash, ck = CK, cs = CS }) ->
[<<TempK1:32/binary, _/binary>>, <<TempK2:32/binary, _/binary>>, _] =
enoise_crypto:hkdf(Hash, CK, <<>>),
{enoise_cipher_state:set_key(CS, TempK1),
enoise_cipher_state:set_key(CS, TempK2)}.
znoise_crypto:hkdf(Hash, CK, <<>>),
{znoise_cipher_state:set_key(CS, TempK1),
znoise_cipher_state:set_key(CS, TempK2)}.
-spec cipher_state(SState :: state()) -> enoise_cipher_state:state().
-spec cipher_state(SState :: state()) -> znoise_cipher_state:state().
cipher_state(#noise_ss{ cs = CS }) ->
CS.
@@ -8,7 +8,11 @@
%%% into Noise packets, so we need some buffering.
%%% @end
-module(enoise_connection).
-module(znoise_tcp).
-vsn("0.1.0").
-author("Craig Everett <craigeverett@qpq.swiss>").
-copyright("QPQ AG <info@qpq.swiss>").
-license("ISC").
-export([controlling_process/2,
close/1,
@@ -20,7 +24,7 @@
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-record(enoise, {pid}).
-record(znoise, {pid}).
-record(s,
{rx = ,
@@ -123,9 +127,9 @@ handle_info({tcp, TS, Data}, State = #s{tcp_sock = TS, owner = O}) ->
NewState = handle_msgs(NextState#s{msgbuf = Buf ++ Msgs}),
set_active(NewState),
{noreply, NewState}
catch error:{enoise_error, _} ->
catch error:{znoise_error, _} ->
%% We are not likely to recover, but leave the decision to upstream
O ! {enoise_error, TS, decrypt_error},
O ! {znoise_error, TS, decrypt_error},
{noreply, State}
end;
handle_info({tcp_closed, TS}, State = #s{tcp_sock = TS, owner = O}) ->
@@ -180,12 +184,12 @@ handle_data(S = #state{ rawbuf = Buf, rx = Rx }, Data) ->
{S#state{ rawbuf = B }, []}; %% Not a full Noise message - save it
<<Len:16, Rest/binary>> ->
<<Msg:Len/binary, Rest2/binary>> = Rest,
case enoise_cipher_state:decrypt_with_ad(Rx, <<>>, Msg) of
case znoise_cipher_state:decrypt_with_ad(Rx, <<>>, Msg) of
{ok, Rx1, Msg1} ->
{S1, Msgs} = handle_data(S#state{ rawbuf = Rest2, rx = Rx1 }, <<>>),
{S1, [Msg1 | Msgs]};
{error, _} ->
error({enoise_error, decrypt_input_failed})
error({znoise_error, decrypt_input_failed})
end;
EmptyOrSingleByte ->
{S#state{ rawbuf = EmptyOrSingleByte }, []}
@@ -194,19 +198,19 @@ handle_data(S = #state{ rawbuf = Buf, rx = Rx }, Data) ->
handle_msgs(S = #state{ msgbuf = [] }) ->
S;
handle_msgs(S = #state{ msgbuf = Msgs, active = true, owner = Owner }) ->
[ Owner ! {noise, #enoise{ pid = self() }, Msg} || Msg <- Msgs ],
[ Owner ! {noise, #znoise{ pid = self() }, Msg} || Msg <- Msgs ],
S#state{ msgbuf = [] };
handle_msgs(S = #state{ msgbuf = [Msg | Msgs], active = {once, Delivered}, owner = Owner }) ->
case Delivered of
true ->
S;
false ->
Owner ! {noise, #enoise{ pid = self() }, Msg},
Owner ! {noise, #znoise{ pid = self() }, Msg},
S#state{ msgbuf = Msgs, active = {once, true} }
end.
handle_send(S = #state{ tcp_sock = TcpSock, tx = Tx }, Data) ->
{ok, Tx1, Msg} = enoise_cipher_state:encrypt_with_ad(Tx, <<>>, Data),
{ok, Tx1, Msg} = znoise_cipher_state:encrypt_with_ad(Tx, <<>>, Data),
case gen_tcp:send(TcpSock, <<(byte_size(Msg)):16, Msg/binary>>) of
ok -> {ok, S#state{ tx = Tx1 }};
Err = {error, _} -> {Err, S}
-56
View File
@@ -1,56 +0,0 @@
%%%-------------------------------------------------------------------
%%% @copyright (C) 2018, Aeternity Anstalt
%%%-------------------------------------------------------------------
-module(enoise_sym_state_tests).
-include_lib("eunit/include/eunit.hrl").
noise_XK_25519_ChaChaPoly_Blake2b_test() ->
Protocol = enoise_protocol:from_name("Noise_XK_25519_ChaChaPoly_BLAKE2b"),
SSE0 = enoise_sym_state:init(Protocol),
SSD0 = enoise_sym_state:init(Protocol),
Name = enoise_protocol:to_name(Protocol),
PadName = enoise_crypto:pad(Name, enoise_crypto:hashlen(blake2b), 0),
?assertMatch(PadName, enoise_sym_state:h(SSE0)),
?assertMatch(PadName, enoise_sym_state:ck(SSE0)),
?assertMatch(false, enoise_cipher_state:has_key(enoise_sym_state:cipher_state(SSE0))),
TestBin = h2b("0x6162636465666768696A6B6C6D6E6F707172737475767778797A"),
SSE1 = enoise_sym_state:mix_hash(SSE0, TestBin),
SSD1 = enoise_sym_state:mix_hash(SSD0, TestBin),
ExpHash1 = enoise_crypto:hash(blake2b, <<PadName/binary, TestBin/binary>>),
ExpHash2 = h2b("0x8DC23DE176F6B3581FB7E18F258A47B1E1A8090BF55978868F1AC88C672DC3918FA4D1828338FB5DF652F5C33D57C79537CB5D074057EF59C346D0B35A160F71"),
?assertMatch(ExpHash1, enoise_sym_state:h(SSE1)),
?assertMatch(ExpHash2, enoise_sym_state:h(SSD1)),
{ok, SSE2, TestBin} = enoise_sym_state:encrypt_and_hash(SSE1, TestBin),
{ok, SSD2, TestBin} = enoise_sym_state:decrypt_and_hash(SSD1, TestBin),
SSE3 = enoise_sym_state:mix_key(SSE2, TestBin),
SSD3 = enoise_sym_state:mix_key(SSD2, TestBin),
ExpEncrypt = h2b("0x24FB13758E6BA9901A4CEA117AE1D9AF757B02CAE96EFDFDA5ED3927BDD9FEA0239F7F673E924AAE81E6"),
{ok, SSE4, Encrypt} = enoise_sym_state:encrypt_and_hash(SSE3, TestBin),
?assertMatch(ExpEncrypt, Encrypt),
{ok, SSD4, Decrypt} = enoise_sym_state:decrypt_and_hash(SSD3, ExpEncrypt),
?assertMatch(TestBin, Decrypt),
Key1 = h2b("0x893FD190EDB611D9AF73868C8AB020F7A13C62F70F7F74C46859CF4A1E71BB74"),
Key2 = h2b("0x492E210AD0181CE70BF9CE80308DE45EAE1FA76E1ACE22A829EF6F1A01C6E2C8"),
{CSE1, CSE2} = enoise_sym_state:split(SSE4),
?assertMatch(Key1, enoise_cipher_state:key(CSE1)),
?assertMatch(Key2, enoise_cipher_state:key(CSE2)),
{CSD1, CSD2} = enoise_sym_state:split(SSD4),
?assertMatch(Key1, enoise_cipher_state:key(CSD1)),
?assertMatch(Key2, enoise_cipher_state:key(CSD2)),
ok.
h2b(S) -> test_utils:hex_str_to_bin(S).
+1 -1
View File
@@ -123,5 +123,5 @@ noise_test_filter(Tests0) ->
Tests1.
supported(Name) ->
try enoise_protocol:from_name(Name), true
try znoise_protocol:from_name(Name), true
catch _:_ -> false end.
@@ -1,15 +1,15 @@
%%%-------------------------------------------------------------------
%%% @copyright (C) 2018, Aeternity Anstalt
%%%-------------------------------------------------------------------
-module(enoise_bad_data_tests).
-module(znoise_bad_data_tests).
-include_lib("eunit/include/eunit.hrl").
bad_data_hs_1_test() ->
SrvKeyPair = enoise_keypair:new(dh25519),
Proto = enoise_protocol:to_name(xk, dh25519, 'ChaChaPoly', blake2b),
SrvKeyPair = znoise_keypair:new(dh25519),
Proto = znoise_protocol:to_name(xk, dh25519, 'ChaChaPoly', blake2b),
Opts = [{echos, 1}, {reply, self()}],
Srv = enoise_utils:echo_srv_start(4567, Proto, SrvKeyPair, Opts),
Srv = znoise_utils:echo_srv_start(4567, Proto, SrvKeyPair, Opts),
bad_client(4567),
@@ -2,7 +2,7 @@
%%% @copyright (C) 2018, Aeternity Anstalt
%%%-------------------------------------------------------------------
-module(enoise_chiper_state_tests).
-module(znoise_chiper_state_tests).
-include_lib("eunit/include/eunit.hrl").
@@ -13,26 +13,26 @@ chachapoly_test() ->
CTLen = byte_size(CipherText),
MACLen = byte_size(MAC),
CS0 = enoise_cipher_state:init(Key, 'ChaChaPoly'),
CS1 = enoise_cipher_state:set_nonce(CS0, Nonce),
CS0 = znoise_cipher_state:init(Key, 'ChaChaPoly'),
CS1 = znoise_cipher_state:set_nonce(CS0, Nonce),
{ok, _CS2, <<CipherText0:CTLen/binary, MAC0:MACLen/binary>>} =
enoise_cipher_state:encrypt_with_ad(CS1, AD, PlainText),
znoise_cipher_state:encrypt_with_ad(CS1, AD, PlainText),
?assertMatch(CipherText, CipherText0),
?assertMatch(MAC, MAC0),
{ok, _CS3, <<PlainText0:PTLen/binary>>} =
enoise_cipher_state:decrypt_with_ad(CS1, AD, <<CipherText/binary, MAC/binary>>),
znoise_cipher_state:decrypt_with_ad(CS1, AD, <<CipherText/binary, MAC/binary>>),
?assertMatch(PlainText, PlainText0),
% rekey test
CS4 = enoise_cipher_state:rekey(CS1),
CS4 = znoise_cipher_state:rekey(CS1),
{ok, _CS5, <<CipherText1:CTLen/binary, MAC1:MACLen/binary>>} =
enoise_cipher_state:encrypt_with_ad(CS4, AD, PlainText),
znoise_cipher_state:encrypt_with_ad(CS4, AD, PlainText),
{ok, _CS6, <<PlainText1:PTLen/binary>>} =
enoise_cipher_state:decrypt_with_ad(CS4, AD, <<CipherText1/binary, MAC1/binary>>),
znoise_cipher_state:decrypt_with_ad(CS4, AD, <<CipherText1/binary, MAC1/binary>>),
?assertMatch(PlainText, PlainText1),
ok.
@@ -2,25 +2,25 @@
%%% @copyright (C) 2018, Aeternity Anstalt
%%%-------------------------------------------------------------------
-module(enoise_crypto_tests).
-module(znoise_crypto_tests).
-include_lib("eunit/include/eunit.hrl").
curve25519_test() ->
KeyPair1 = enoise_keypair:new(dh25519),
KeyPair2 = enoise_keypair:new(dh25519),
KeyPair1 = znoise_keypair:new(dh25519),
KeyPair2 = znoise_keypair:new(dh25519),
SharedA = enoise_crypto:dh(dh25519, KeyPair1, KeyPair2),
SharedB = enoise_crypto:dh(dh25519, KeyPair2, KeyPair1),
SharedA = znoise_crypto:dh(dh25519, KeyPair1, KeyPair2),
SharedB = znoise_crypto:dh(dh25519, KeyPair2, KeyPair1),
?assertMatch(SharedA, SharedB),
#{ a_pub := APub, a_priv := APriv,
b_pub := BPub, b_priv := BPriv, shared := Shared } = test_utils:curve25519_data(),
KeyPair3 = enoise_keypair:new(dh25519, APriv, APub),
KeyPair4 = enoise_keypair:new(dh25519, BPriv, BPub),
?assertMatch(Shared, enoise_crypto:dh(dh25519, KeyPair3, KeyPair4)),
?assertMatch(Shared, enoise_crypto:dh(dh25519, KeyPair4, KeyPair3)),
KeyPair3 = znoise_keypair:new(dh25519, APriv, APub),
KeyPair4 = znoise_keypair:new(dh25519, BPriv, BPub),
?assertMatch(Shared, znoise_crypto:dh(dh25519, KeyPair3, KeyPair4)),
?assertMatch(Shared, znoise_crypto:dh(dh25519, KeyPair4, KeyPair3)),
ok.
@@ -35,43 +35,43 @@ chachapoly_test() ->
?assert(PTLen == CTLen),
<<CipherText0:CTLen/binary, MAC0:MACLen/binary>> =
enoise_crypto:encrypt('ChaChaPoly', Key, Nonce, AD, PlainText),
znoise_crypto:encrypt('ChaChaPoly', Key, Nonce, AD, PlainText),
?assertMatch(CipherText, CipherText0),
?assertMatch(MAC, MAC0),
<<PlainText0:PTLen/binary>> =
enoise_crypto:decrypt('ChaChaPoly', Key, Nonce, AD, <<CipherText/binary, MAC/binary>>),
znoise_crypto:decrypt('ChaChaPoly', Key, Nonce, AD, <<CipherText/binary, MAC/binary>>),
?assertMatch(PlainText, PlainText0),
Key1 = enoise_crypto:rekey('ChaChaPoly', Key),
Key1 = znoise_crypto:rekey('ChaChaPoly', Key),
<<CipherText1:CTLen/binary, MAC1:MACLen/binary>> =
enoise_crypto:encrypt('ChaChaPoly', Key1, Nonce, AD, PlainText),
znoise_crypto:encrypt('ChaChaPoly', Key1, Nonce, AD, PlainText),
<<PlainText1:PTLen/binary>> =
enoise_crypto:decrypt('ChaChaPoly', Key1, Nonce, AD, <<CipherText1/binary, MAC1/binary>>),
znoise_crypto:decrypt('ChaChaPoly', Key1, Nonce, AD, <<CipherText1/binary, MAC1/binary>>),
?assertMatch(PlainText, PlainText1),
ok.
blake2b_test() ->
Test = fun(#{ input := In, output := Out }) ->
?assertMatch(Out, enoise_crypto:hash(blake2b, In))
?assertMatch(Out, znoise_crypto:hash(blake2b, In))
end,
lists:foreach(Test, test_utils:blake2b_data()).
%% blake2s_test() ->
%% #{ input := In, output := Out } = test_utils:blake2s_data(),
%% ?assertMatch(Out, enoise_crypto:hash(blake2s, In)).
%% ?assertMatch(Out, znoise_crypto:hash(blake2s, In)).
blake2b_hmac_test() ->
Test = fun(#{ key := Key, data := Data, hmac := HMAC }) ->
?assertMatch(HMAC, enoise_crypto:hmac(blake2b, Key, Data))
?assertMatch(HMAC, znoise_crypto:hmac(blake2b, Key, Data))
end,
lists:foreach(Test, test_utils:blake2b_hmac_data()).
blake2b_hkdf_test() ->
Test = fun(#{ key := Key, data := Data, out1 := Out1, out2 := Out2 }) ->
?assertMatch([Out1, Out2, _], enoise_crypto:hkdf(blake2b, Key, Data))
?assertMatch([Out1, Out2, _], znoise_crypto:hkdf(blake2b, Key, Data))
end,
lists:foreach(Test, test_utils:blake2b_hkdf_data()).
@@ -2,7 +2,7 @@
%%% @copyright (C) 2018, Aeternity Anstalt
%%%-------------------------------------------------------------------
-module(enoise_hs_state_tests).
-module(znoise_hs_state_tests).
-include_lib("eunit/include/eunit.hrl").
@@ -18,7 +18,7 @@ noise_hs_test_() ->
}.
noise_hs_test(V = #{ protocol_name := Name }) ->
Protocol = enoise_protocol:from_name(Name),
Protocol = znoise_protocol:from_name(Name),
FixK = fun(undefined) -> undefined;
(Bin) -> test_utils:hex_str_to_bin("0x" ++ binary_to_list(Bin)) end,
@@ -39,11 +39,11 @@ noise_hs_test(V = #{ protocol_name := Name }) ->
ok.
noise_test(_Name, Protocol, Init, Resp, Messages, HSHash) ->
DH = enoise_protocol:dh(Protocol),
SecK = fun(undefined) -> undefined; (Sec) -> enoise_keypair:new(DH, Sec, undefined) end,
PubK = fun(undefined) -> undefined; (Pub) -> enoise_keypair:new(DH, Pub) end,
DH = znoise_protocol:dh(Protocol),
SecK = fun(undefined) -> undefined; (Sec) -> znoise_keypair:new(DH, Sec, undefined) end,
PubK = fun(undefined) -> undefined; (Pub) -> znoise_keypair:new(DH, Pub) end,
HSInit = fun(P, R, #{ e := E, s := S, rs := RS, prologue := PL }) ->
{ok, HS} = enoise_hs_state:init(P, R, PL, {SecK(S), SecK(E), PubK(RS), undefined}),
{ok, HS} = znoise_hs_state:init(P, R, PL, {SecK(S), SecK(E), PubK(RS), undefined}),
HS
end,
@@ -57,16 +57,16 @@ noise_test(_Name, Protocol, Init, Resp, Messages, HSHash) ->
noise_test([M = #{ payload := PL0, ciphertext := CT0 } | Msgs], SendHS, RecvHS, HSHash) ->
PL = test_utils:hex_str_to_bin("0x" ++ binary_to_list(PL0)),
CT = test_utils:hex_str_to_bin("0x" ++ binary_to_list(CT0)),
case {enoise_hs_state:next_message(SendHS), enoise_hs_state:next_message(RecvHS)} of
case {znoise_hs_state:next_message(SendHS), znoise_hs_state:next_message(RecvHS)} of
{out, in} ->
{ok, SendHS1, Message} = enoise_hs_state:write_message(SendHS, PL),
{ok, SendHS1, Message} = znoise_hs_state:write_message(SendHS, PL),
?assertEqual(CT, Message),
{ok, RecvHS1, PL1} = enoise_hs_state:read_message(RecvHS, Message),
{ok, RecvHS1, PL1} = znoise_hs_state:read_message(RecvHS, Message),
?assertEqual(PL, PL1),
noise_test(Msgs, RecvHS1, SendHS1, HSHash);
{done, done} ->
{ok, #{ rx := RX1, tx := TX1, hs_hash := HSHash1 }} = enoise_hs_state:finalize(SendHS),
{ok, #{ rx := RX2, tx := TX2, hs_hash := HSHash2 }} = enoise_hs_state:finalize(RecvHS),
{ok, #{ rx := RX1, tx := TX1, hs_hash := HSHash1 }} = znoise_hs_state:finalize(SendHS),
{ok, #{ rx := RX2, tx := TX2, hs_hash := HSHash2 }} = znoise_hs_state:finalize(RecvHS),
?assertEqual(RX1, TX2), ?assertEqual(RX2, TX1),
?assertEqual(HSHash, HSHash1), ?assertEqual(HSHash, HSHash2),
noise_test([M | Msgs], TX1, RX1);
@@ -77,9 +77,9 @@ noise_test([], _, _) -> ok;
noise_test([#{ payload := PL0, ciphertext := CT0 } | Msgs], CA, CB) ->
PL = test_utils:hex_str_to_bin("0x" ++ binary_to_list(PL0)),
CT = test_utils:hex_str_to_bin("0x" ++ binary_to_list(CT0)),
{ok, CA1, CT1} = enoise_cipher_state:encrypt_with_ad(CA, <<>>, PL),
{ok, CA1, CT1} = znoise_cipher_state:encrypt_with_ad(CA, <<>>, PL),
?assertEqual(CT, CT1),
{ok, CA2, PL1} = enoise_cipher_state:decrypt_with_ad(CA, <<>>, CT1),
{ok, CA2, PL1} = znoise_cipher_state:decrypt_with_ad(CA, <<>>, CT1),
?assertEqual(CA1, CA2),
?assertEqual(PL, PL1),
noise_test(Msgs, CB, CA1).
@@ -2,7 +2,7 @@
%%% @copyright (C) 2018, Aeternity Anstalt
%%%-------------------------------------------------------------------
-module(enoise_protocol_tests).
-module(znoise_protocol_tests).
-include_lib("eunit/include/eunit.hrl").
@@ -12,13 +12,13 @@ name_test() ->
name2_test() ->
Name = "Noise_NXpsk2_25519_AESGCM_SHA512",
?assertError({name_not_recognized, Name}, enoise_protocol:from_name(Name)).
?assertError({name_not_recognized, Name}, znoise_protocol:from_name(Name)).
name_pattern_test() ->
Pat = "XKfallback+psk0",
RoundPat = enoise_protocol:to_name_pattern(enoise_protocol:from_name_pattern(Pat)),
RoundPat = znoise_protocol:to_name_pattern(znoise_protocol:from_name_pattern(Pat)),
?assertEqual(Pat, RoundPat).
roundtrip(Name) ->
ExpectedName = iolist_to_binary(Name),
?assertMatch(ExpectedName, enoise_protocol:to_name(enoise_protocol:from_name(Name))).
?assertMatch(ExpectedName, znoise_protocol:to_name(znoise_protocol:from_name(Name))).
+56
View File
@@ -0,0 +1,56 @@
%%%-------------------------------------------------------------------
%%% @copyright (C) 2018, Aeternity Anstalt
%%%-------------------------------------------------------------------
-module(znoise_sym_state_tests).
-include_lib("eunit/include/eunit.hrl").
noise_XK_25519_ChaChaPoly_Blake2b_test() ->
Protocol = znoise_protocol:from_name("Noise_XK_25519_ChaChaPoly_BLAKE2b"),
SSE0 = znoise_sym_state:init(Protocol),
SSD0 = znoise_sym_state:init(Protocol),
Name = znoise_protocol:to_name(Protocol),
PadName = znoise_crypto:pad(Name, znoise_crypto:hashlen(blake2b), 0),
?assertMatch(PadName, znoise_sym_state:h(SSE0)),
?assertMatch(PadName, znoise_sym_state:ck(SSE0)),
?assertMatch(false, znoise_cipher_state:has_key(znoise_sym_state:cipher_state(SSE0))),
TestBin = h2b("0x6162636465666768696A6B6C6D6E6F707172737475767778797A"),
SSE1 = znoise_sym_state:mix_hash(SSE0, TestBin),
SSD1 = znoise_sym_state:mix_hash(SSD0, TestBin),
ExpHash1 = znoise_crypto:hash(blake2b, <<PadName/binary, TestBin/binary>>),
ExpHash2 = h2b("0x8DC23DE176F6B3581FB7E18F258A47B1E1A8090BF55978868F1AC88C672DC3918FA4D1828338FB5DF652F5C33D57C79537CB5D074057EF59C346D0B35A160F71"),
?assertMatch(ExpHash1, znoise_sym_state:h(SSE1)),
?assertMatch(ExpHash2, znoise_sym_state:h(SSD1)),
{ok, SSE2, TestBin} = znoise_sym_state:encrypt_and_hash(SSE1, TestBin),
{ok, SSD2, TestBin} = znoise_sym_state:decrypt_and_hash(SSD1, TestBin),
SSE3 = znoise_sym_state:mix_key(SSE2, TestBin),
SSD3 = znoise_sym_state:mix_key(SSD2, TestBin),
ExpEncrypt = h2b("0x24FB13758E6BA9901A4CEA117AE1D9AF757B02CAE96EFDFDA5ED3927BDD9FEA0239F7F673E924AAE81E6"),
{ok, SSE4, Encrypt} = znoise_sym_state:encrypt_and_hash(SSE3, TestBin),
?assertMatch(ExpEncrypt, Encrypt),
{ok, SSD4, Decrypt} = znoise_sym_state:decrypt_and_hash(SSD3, ExpEncrypt),
?assertMatch(TestBin, Decrypt),
Key1 = h2b("0x893FD190EDB611D9AF73868C8AB020F7A13C62F70F7F74C46859CF4A1E71BB74"),
Key2 = h2b("0x492E210AD0181CE70BF9CE80308DE45EAE1FA76E1ACE22A829EF6F1A01C6E2C8"),
{CSE1, CSE2} = znoise_sym_state:split(SSE4),
?assertMatch(Key1, znoise_cipher_state:key(CSE1)),
?assertMatch(Key2, znoise_cipher_state:key(CSE2)),
{CSD1, CSD2} = znoise_sym_state:split(SSD4),
?assertMatch(Key1, znoise_cipher_state:key(CSD1)),
?assertMatch(Key2, znoise_cipher_state:key(CSD2)),
ok.
h2b(S) -> test_utils:hex_str_to_bin(S).
+39 -39
View File
@@ -2,7 +2,7 @@
%%% @copyright (C) 2018, Aeternity Anstalt
%%%-------------------------------------------------------------------
-module(enoise_tests).
-module(znoise_tests).
-include_lib("eunit/include/eunit.hrl").
@@ -18,7 +18,7 @@ noise_interactive_test_() ->
}.
noise_interactive(V = #{ protocol_name := Name }) ->
Protocol = enoise_protocol:from_name(Name),
Protocol = znoise_protocol:from_name(Name),
FixK = fun(undefined) -> undefined;
(Bin) -> test_utils:hex_str_to_bin("0x" ++ binary_to_list(Bin)) end,
@@ -39,12 +39,12 @@ noise_interactive(V = #{ protocol_name := Name }) ->
ok.
noise_interactive(_Name, Protocol, Init, Resp, Messages, HSHash) ->
DH = enoise_protocol:dh(Protocol),
SecK = fun(undefined) -> undefined; (Sec) -> enoise_keypair:new(DH, Sec, undefined) end,
DH = znoise_protocol:dh(Protocol),
SecK = fun(undefined) -> undefined; (Sec) -> znoise_keypair:new(DH, Sec, undefined) end,
HSInit = fun(#{ e := E, s := S, rs := RS, prologue := PL }, R) ->
Opts = [{noise, Protocol}, {s, SecK(S)}, {e, SecK(E)}, {rs, RS}, {prologue, PL}],
enoise:handshake(Opts, R)
znoise:handshake(Opts, R)
end,
{ok, InitHS} = HSInit(Init, initiator),
{ok, RespHS} = HSInit(Resp, responder),
@@ -54,16 +54,16 @@ noise_interactive(_Name, Protocol, Init, Resp, Messages, HSHash) ->
noise_interactive([#{ payload := PL0, ciphertext := CT0 } | Msgs], SendHS, RecvHS, HSHash) ->
PL = test_utils:hex_str_to_bin("0x" ++ binary_to_list(PL0)),
CT = test_utils:hex_str_to_bin("0x" ++ binary_to_list(CT0)),
case enoise_hs_state:next_message(SendHS) of
case znoise_hs_state:next_message(SendHS) of
out ->
{ok, send, Message, SendHS1} = enoise:step_handshake(SendHS, {send, PL}),
{ok, send, Message, SendHS1} = znoise:step_handshake(SendHS, {send, PL}),
?assertEqual(CT, Message),
{ok, rcvd, PL1, RecvHS1} = enoise:step_handshake(RecvHS, {rcvd, Message}),
{ok, rcvd, PL1, RecvHS1} = znoise:step_handshake(RecvHS, {rcvd, Message}),
?assertEqual(PL, PL1),
noise_interactive(Msgs, RecvHS1, SendHS1, HSHash);
done ->
{ok, done, #{ rx := RX1, tx := TX1, hs_hash := HSHash1 }} = enoise:step_handshake(SendHS, done),
{ok, done, #{ rx := RX2, tx := TX2, hs_hash := HSHash2 }} = enoise:step_handshake(RecvHS, done),
{ok, done, #{ rx := RX1, tx := TX1, hs_hash := HSHash1 }} = znoise:step_handshake(SendHS, done),
{ok, done, #{ rx := RX2, tx := TX2, hs_hash := HSHash2 }} = znoise:step_handshake(RecvHS, done),
?assertEqual(RX1, TX2), ?assertEqual(RX2, TX1),
?assertEqual(HSHash, HSHash1), ?assertEqual(HSHash, HSHash2)
end.
@@ -89,19 +89,19 @@ noise_monitor_test_() ->
setup_dh25519() ->
%% Generate a static key-pair for Client and Server
SrvKeyPair = enoise_keypair:new(dh25519),
CliKeyPair = enoise_keypair:new(dh25519),
SrvKeyPair = znoise_keypair:new(dh25519),
CliKeyPair = znoise_keypair:new(dh25519),
#{ hs_pattern := Ps, hash := Hs, cipher := Cs } = enoise_protocol:supported(),
Configurations = [ enoise_protocol:to_name(P, dh25519, C, H)
#{ hs_pattern := Ps, hash := Hs, cipher := Cs } = znoise_protocol:supported(),
Configurations = [ znoise_protocol:to_name(P, dh25519, C, H)
|| P <- Ps, C <- Cs, H <- Hs ],
%% Configurations = [ enoise_protocol:to_name(xk, dh25519, 'ChaChaPoly', blake2b) ],
%% Configurations = [ znoise_protocol:to_name(xk, dh25519, 'ChaChaPoly', blake2b) ],
{Configurations, SrvKeyPair, CliKeyPair}.
noise_test(Conf, SKP, CKP) ->
#{econn := EConn, echo_srv := EchoSrv} = noise_test_run(Conf, SKP, CKP),
enoise:close(EConn),
enoise_utils:echo_srv_stop(EchoSrv),
znoise:close(EConn),
znoise_utils:echo_srv_stop(EchoSrv),
ok.
noise_test_run(Conf, SKP, CKP) ->
@@ -145,25 +145,25 @@ proxy_exec(P, F) when is_function(F, 0) ->
end.
noise_test_run_(Conf, SKP, CKP) ->
Protocol = enoise_protocol:from_name(Conf),
Protocol = znoise_protocol:from_name(Conf),
Port = 4556,
SrvOpts = [{echos, 2}, {cpub, enoise_keypair:pubkey(CKP)}],
EchoSrv = enoise_utils:echo_srv_start(Port, Protocol, SKP, SrvOpts),
SrvOpts = [{echos, 2}, {cpub, znoise_keypair:pubkey(CKP)}],
EchoSrv = znoise_utils:echo_srv_start(Port, Protocol, SKP, SrvOpts),
{ok, TcpSock} = gen_tcp:connect("localhost", Port, [{active, once}, binary, {reuseaddr, true}], 100),
Opts = [{noise, Protocol}, {s, CKP}] ++ [{rs, enoise_keypair:pubkey(SKP)} || enoise_utils:need_rs(initiator, Conf) ],
{ok, EConn, _} = enoise:connect(TcpSock, Opts),
Opts = [{noise, Protocol}, {s, CKP}] ++ [{rs, znoise_keypair:pubkey(SKP)} || znoise_utils:need_rs(initiator, Conf) ],
{ok, EConn, _} = znoise:connect(TcpSock, Opts),
ok = enoise:send(EConn, <<"Hello World!">>),
ok = znoise:send(EConn, <<"Hello World!">>),
receive
{noise, _, <<"Hello World!">>} -> ok
after 100 -> error(timeout) end,
enoise:set_active(EConn, once),
znoise:set_active(EConn, once),
ok = enoise:send(EConn, <<"Goodbye!">>),
ok = znoise:send(EConn, <<"Goodbye!">>),
receive
{noise, _, <<"Goodbye!">>} -> ok
after 100 -> error(timeout) end,
@@ -172,7 +172,7 @@ noise_test_run_(Conf, SKP, CKP) ->
, echo_srv => EchoSrv }.
noise_monitor_test(Conf, SKP, CKP) ->
#{ econn := {enoise, EConnPid}
#{ econn := {znoise, EConnPid}
, proxy := Proxy
, tcp_sock := _TcpSock } = noise_test_run(Conf, SKP, CKP),
try proxy_exec(Proxy, fun() -> exit(normal) end)
@@ -185,7 +185,7 @@ noise_monitor_test(Conf, SKP, CKP) ->
%% Talks to local echo-server (noise-c)
%% client_test() ->
%% TestProtocol = enoise_protocol:from_name("Noise_XK_25519_ChaChaPoly_BLAKE2b"),
%% TestProtocol = znoise_protocol:from_name("Noise_XK_25519_ChaChaPoly_BLAKE2b"),
%% ClientPrivKey = <<64,168,119,119,151,194,94,141,86,245,144,220,78,53,243,231,168,216,66,199,49,148,202,117,98,40,61,109,170,37,133,122>>,
%% ClientPubKey = <<115,39,86,77,44,85,192,176,202,11,4,6,194,144,127,123, 34,67,62,180,190,232,251,5,216,168,192,190,134,65,13,64>>,
%% ServerPubKey = <<112,91,141,253,183,66,217,102,211,40,13,249,238,51,77,114,163,159,32,1,162,219,76,106,89,164,34,71,149,2,103,59>>,
@@ -194,29 +194,29 @@ noise_monitor_test(Conf, SKP, CKP) ->
%% gen_tcp:send(TcpSock, <<0,8,0,0,3>>), %% "Noise_XK_25519_ChaChaPoly_Blake2b"
%% Opts = [ {noise, TestProtocol}
%% , {s, enoise_keypair:new(dh25519, ClientPrivKey, ClientPubKey)}
%% , {rs, enoise_keypair:new(dh25519, ServerPubKey)}
%% , {s, znoise_keypair:new(dh25519, ClientPrivKey, ClientPubKey)}
%% , {rs, znoise_keypair:new(dh25519, ServerPubKey)}
%% , {prologue, <<0,8,0,0,3>>}],
%% {ok, EConn} = enoise:connect(TcpSock, Opts),
%% ok = enoise:send(EConn, <<"ok\n">>),
%% {ok, EConn} = znoise:connect(TcpSock, Opts),
%% ok = znoise:send(EConn, <<"ok\n">>),
%% receive
%% {noise, EConn, <<"ok\n">>} -> ok
%% after 1000 -> error(timeout) end,
%% %% {ok, <<"ok\n">>} = enoise:recv(EConn, 3, 1000),
%% enoise:close(EConn).
%% %% {ok, <<"ok\n">>} = znoise:recv(EConn, 3, 1000),
%% znoise:close(EConn).
%% Expects a call-in from a local echo-client (noise-c)
%% server_test_() ->
%% {timeout, 20, fun() ->
%% TestProtocol = enoise_protocol:from_name("Noise_XK_25519_ChaChaPoly_Blake2b"),
%% TestProtocol = znoise_protocol:from_name("Noise_XK_25519_ChaChaPoly_Blake2b"),
%% ServerPrivKey = <<200,81,196,192,228,196,182,200,181,83,169,255,242,54,99,113,8,49,129,92,225,220,99,50,93,96,253,250,116,196,137,103>>,
%% ServerPubKey = <<112,91,141,253,183,66,217,102,211,40,13,249,238,51,77,114,163,159,32,1,162,219,76,106,89,164,34,71,149,2,103,59>>,
%% Opts = [ {noise, TestProtocol}
%% , {s, enoise_keypair:new(dh25519, ServerPrivKey, ServerPubKey)}
%% , {s, znoise_keypair:new(dh25519, ServerPrivKey, ServerPubKey)}
%% , {prologue, <<0,8,0,0,3>>}],
%% {ok, LSock} = gen_tcp:listen(7891, [{reuseaddr, true}, binary]),
@@ -226,12 +226,12 @@ noise_monitor_test(Conf, SKP, CKP) ->
%% receive {tcp, TcpSock, <<0,8,0,0,3>>} -> ok
%% after 1000 -> error(timeout) end,
%% {ok, EConn} = enoise:accept(TcpSock, Opts),
%% {ok, EConn} = znoise:accept(TcpSock, Opts),
%% {EConn1, Msg} = enoise:recv(EConn),
%% EConn2 = enoise:send(EConn1, Msg),
%% {EConn1, Msg} = znoise:recv(EConn),
%% EConn2 = znoise:send(EConn1, Msg),
%% enoise:close(EConn2)
%% znoise:close(EConn2)
%% end}.
@@ -2,7 +2,7 @@
%%% @copyright (C) 2018, Aeternity Anstalt
%%%-------------------------------------------------------------------
-module(enoise_utils).
-module(znoise_utils).
-compile([export_all, nowarn_export_all]).
@@ -25,7 +25,7 @@ echo_srv(Port, Protocol, SKP, SrvOpts) ->
AcceptRes =
try
enoise:accept(TcpSock, Opts)
znoise:accept(TcpSock, Opts)
catch _:R:S -> gen_tcp:close(TcpSock), {error, {R, S}} end,
gen_tcp:close(LSock),
@@ -46,7 +46,7 @@ echo_srv_loop(EConn, SrvOpts) ->
end;
active ->
fun() ->
{ok, Msg} = enoise:recv(EConn, 0, 100),
{ok, Msg} = znoise:recv(EConn, 0, 100),
Msg
end
end,
@@ -56,14 +56,14 @@ echo_srv_loop(EConn, SrvOpts) ->
try
[ begin
Msg = Recv(),
ok = enoise:send(EConn, Msg)
ok = znoise:send(EConn, Msg)
end || _ <- lists:seq(1, Echos) ],
ok
catch _:R -> {error, R} end,
srv_reply(Res, SrvOpts),
enoise:close(EConn),
znoise:close(EConn),
Res.
@@ -74,8 +74,8 @@ srv_reply(Reply, SrvOpts) ->
end.
need_rs(Role, Conf) when is_binary(Conf) ->
need_rs(Role, enoise_protocol:from_name(Conf));
need_rs(Role, znoise_protocol:from_name(Conf));
need_rs(Role, Protocol) ->
PreMsgs = enoise_protocol:pre_msgs(Role, Protocol),
PreMsgs = znoise_protocol:pre_msgs(Role, Protocol),
lists:member({in, [s]}, PreMsgs).
+17
View File
@@ -0,0 +1,17 @@
{name,"zNoise"}.
{type,lib}.
{modules,[]}.
{prefix,none}.
{desc,"An Erlang implementation of the Noise protocol, adapted for zx"}.
{author,"Craig Everett"}.
{package_id,{"otpr","znoise",{0,1,0}}}.
{deps,[]}.
{key_name,none}.
{a_email,"craigeverett@qpq.swiss"}.
{c_email,"craigeverett@qpq.swiss"}.
{copyright,"Craig Everett"}.
{file_exts,[]}.
{license,"ISC"}.
{repo_url,"https://git.qpq.swiss/zxq9/zNoise"}.
{tags,[]}.
{ws_url,"https://git.qpq.swiss/zxq9/zNoise"}.