The innermost layer cipher_state
This commit is contained in:
parent
cb626ab07c
commit
d78c774b55
25
include/enoise.hrl
Normal file
25
include/enoise.hrl
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
-define(MAX_NONCE, 16#FFFFFFFFFFFFFFFF).
|
||||||
|
-define(AD_LEN, 16).
|
||||||
|
|
||||||
|
-record(noise_protocol,
|
||||||
|
{ hs_pattern = noiseNN %:: noise_hs_pattern()
|
||||||
|
, dh = dh25519 %:: noise_dh()
|
||||||
|
, cipher = 'ChaChaPoly' %:: noise_cipher()
|
||||||
|
, hash = blake2b %:: noise_hash()
|
||||||
|
}).
|
||||||
|
|
||||||
|
-record(key_pair, { puk, pik }).
|
||||||
|
|
||||||
|
-record(noise_ss, { cs :: enoise_cipher_state:state()
|
||||||
|
, ck = <<>> :: binary()
|
||||||
|
, h = <<>> :: binary()
|
||||||
|
, hash = blake2b }).
|
||||||
|
|
||||||
|
-record(noise_hs, { ss :: #noise_ss{} | undefined
|
||||||
|
, s :: #key_pair{} | undefined
|
||||||
|
, e :: #key_pair{} | undefined
|
||||||
|
, rs :: binary() | undefined
|
||||||
|
, re :: binary() | undefined
|
||||||
|
, role = initiatior :: initiator | responder
|
||||||
|
, dh
|
||||||
|
, msgs = [] }).
|
72
src/enoise_cipher_state.erl
Normal file
72
src/enoise_cipher_state.erl
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @copyright (C) 2018, Aeternity Anstalt
|
||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
|
-module(enoise_cipher_state).
|
||||||
|
|
||||||
|
-export([ cipher/1
|
||||||
|
, decrypt_with_ad/3
|
||||||
|
, encrypt_with_ad/3
|
||||||
|
, has_key/1
|
||||||
|
, init/2
|
||||||
|
, rekey/1
|
||||||
|
, set_key/2
|
||||||
|
, set_nonce/2
|
||||||
|
]).
|
||||||
|
|
||||||
|
-include("enoise.hrl").
|
||||||
|
|
||||||
|
-type noise_cipher() :: 'ChaChaPoly' | 'AESGCM'.
|
||||||
|
-type nonce() :: non_neg_integer().
|
||||||
|
-type key() :: empty | binary().
|
||||||
|
|
||||||
|
-record(noise_cs, { k = empty :: key()
|
||||||
|
, n = 0 :: nonce()
|
||||||
|
, cipher = 'ChaChaPoly' :: noise_cipher() }).
|
||||||
|
|
||||||
|
-opaque state() :: #noise_cs{}.
|
||||||
|
|
||||||
|
-export_type([noise_cipher/0, state/0]).
|
||||||
|
|
||||||
|
-spec init(Key :: key(), Cipher :: noise_cipher()) -> state().
|
||||||
|
init(Key, Cipher) ->
|
||||||
|
#noise_cs{ k = Key, n = 0, cipher = Cipher }.
|
||||||
|
|
||||||
|
-spec set_key(CState :: state(), NewKey :: key()) -> state().
|
||||||
|
set_key(CState, NewKey) ->
|
||||||
|
CState#noise_cs{ k = NewKey, n = 0 }.
|
||||||
|
|
||||||
|
-spec has_key(CState :: state()) -> boolean().
|
||||||
|
has_key(#noise_cs{ k = Key }) ->
|
||||||
|
Key =/= empty.
|
||||||
|
|
||||||
|
-spec set_nonce(CState :: state(), NewNonce :: nonce()) -> state().
|
||||||
|
set_nonce(CState = #noise_cs{}, Nonce) ->
|
||||||
|
CState#noise_cs{ n = Nonce }.
|
||||||
|
|
||||||
|
-spec encrypt_with_ad(CState :: state(), AD :: binary(), PlainText :: binary()) ->
|
||||||
|
{ok, state(), binary()}.
|
||||||
|
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) ->
|
||||||
|
{ok, CState#noise_cs{ n = N+1 }, enoise_crypto:encrypt(Cipher, K, N, AD, PlainText)}.
|
||||||
|
|
||||||
|
-spec decrypt_with_ad(CState :: state(), AD :: binary(), CipherText :: binary()) ->
|
||||||
|
{ok, state(), binary()} | {error, term()}.
|
||||||
|
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
|
||||||
|
PlainText when is_binary(PlainText) ->
|
||||||
|
{ok, CState#noise_cs{ n = N+1 }, PlainText};
|
||||||
|
Err = {error, _} ->
|
||||||
|
Err
|
||||||
|
end.
|
||||||
|
|
||||||
|
-spec rekey(CState :: state()) -> state().
|
||||||
|
rekey(CState = #noise_cs{ k = K, cipher = Cipher }) ->
|
||||||
|
CState#noise_cs{ k = enoise_crypto:rekey(Cipher, K) }.
|
||||||
|
|
||||||
|
-spec cipher(CState :: state()) -> noise_cipher().
|
||||||
|
cipher(#noise_cs{ cipher = Cipher }) ->
|
||||||
|
Cipher.
|
54
src/enoise_crypto.erl
Normal file
54
src/enoise_crypto.erl
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @copyright (C) 2018, Aeternity Anstalt
|
||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
|
-module(enoise_crypto).
|
||||||
|
|
||||||
|
-include("enoise.hrl").
|
||||||
|
|
||||||
|
-export([decrypt/5, encrypt/5, rekey/2, hash/2, pad/3, hashlen/1, dhlen/1, new_key_pair/1, hkdf/3, dh/3]).
|
||||||
|
|
||||||
|
new_key_pair(dh25519) ->
|
||||||
|
KeyPair = enacl:crypto_sign_ed25519_keypair(),
|
||||||
|
#key_pair{ puk = enacl:crypto_sign_ed25519_public_to_curve25519(maps:get(public, KeyPair))
|
||||||
|
, pik = enacl:crypto_sign_ed25519_secret_to_curve25519(maps:get(secret, KeyPair)) }.
|
||||||
|
|
||||||
|
dh(dh25519, KeyPair, PubKey) ->
|
||||||
|
enacl:curve25519_scalarmult(KeyPair#key_pair.pik, PubKey).
|
||||||
|
|
||||||
|
hkdf(_, _, _) -> [].
|
||||||
|
|
||||||
|
rekey(Cipher, K) ->
|
||||||
|
encrypt(Cipher, K, ?MAX_NONCE, <<>>, <<0:(32*8)>>).
|
||||||
|
|
||||||
|
encrypt('ChaChaPoly', K, N, Ad, PlainText) ->
|
||||||
|
enacl:aead_chacha20poly1305_encrypt(K, N, Ad, PlainText).
|
||||||
|
|
||||||
|
-spec decrypt(Cipher ::enoise_cipher_state:noise_cipher(),
|
||||||
|
Key :: binary(), Nonce :: non_neg_integer(),
|
||||||
|
AD :: binary(), CipherText :: binary()) ->
|
||||||
|
binary() | {error, term()}.
|
||||||
|
decrypt('ChaChaPoly', K, N, Ad, CipherText) ->
|
||||||
|
enacl:aead_chacha20poly1305_decrypt(K, N, Ad, CipherText).
|
||||||
|
|
||||||
|
hash(blake2b, Data) ->
|
||||||
|
enacl:generichash(64, Data);
|
||||||
|
hash(blake2s, Data) ->
|
||||||
|
enacl:generichash(32, Data).
|
||||||
|
|
||||||
|
pad(Data, MinSize, PadByte) ->
|
||||||
|
case byte_size(Data) of
|
||||||
|
N when N >= MinSize ->
|
||||||
|
Data;
|
||||||
|
N ->
|
||||||
|
PadData = << <<PadByte:8>> || _ <- lists:seq(1, MinSize - N) >>,
|
||||||
|
<<Data/binary, PadData/binary>>
|
||||||
|
end.
|
||||||
|
|
||||||
|
hashlen(sha256) -> 32;
|
||||||
|
hashlen(sha512) -> 64;
|
||||||
|
hashlen(blake2s) -> 32;
|
||||||
|
hashlen(blake2b) -> 64.
|
||||||
|
|
||||||
|
dhlen(dh25519) -> 32;
|
||||||
|
dhlen(dh448) -> 56.
|
Loading…
x
Reference in New Issue
Block a user