forked from QPQ-AG/enoise
81 lines
2.6 KiB
Erlang
81 lines
2.6 KiB
Erlang
%%% ------------------------------------------------------------------
|
|
%%% @copyright 2018, Aeternity Anstalt
|
|
%%%
|
|
%%% @doc Module is an abstract data type for a key pair.
|
|
%%%
|
|
%%% @end
|
|
%%% ------------------------------------------------------------------
|
|
|
|
-module(enoise_keypair).
|
|
|
|
-export([ key_type/1
|
|
, new/1
|
|
, new/2
|
|
, new/3
|
|
, pubkey/1
|
|
, seckey/1
|
|
]).
|
|
|
|
-type key_type() :: dh25519 | dh448.
|
|
|
|
-record(kp, { type :: key_type()
|
|
, sec :: binary() | undefined
|
|
, pub :: binary() }).
|
|
|
|
-opaque keypair() :: #kp{}.
|
|
%% Abstract keypair holding a secret key/public key pair and its type.
|
|
|
|
-export_type([keypair/0]).
|
|
|
|
%% @doc Generate a new keypair of type `Type'.
|
|
-spec new(Type :: key_type()) -> keypair().
|
|
new(Type) ->
|
|
{Sec, Pub} = new_key_pair(Type),
|
|
#kp{ type = Type, sec = Sec, pub = Pub }.
|
|
|
|
%% @doc Create a new keypair of type `Type'. If `Public' is `undefined'
|
|
%% it will be computed from the `Secret' (using the curve/algorithm
|
|
%% indicated by `Type').
|
|
-spec new(Type :: key_type(),
|
|
Secret :: binary() | undefined,
|
|
Public :: binary() | undefined) -> keypair().
|
|
new(Type, Secret, undefined) ->
|
|
new(Type, Secret, pubkey_from_secret(Type, Secret));
|
|
new(Type, Secret, Public) ->
|
|
#kp{ type = Type, sec = Secret, pub = Public }.
|
|
|
|
%% @doc Define a "public only" keypair - holding just a public key and
|
|
%% `undefined' for secret key.
|
|
-spec new(Type :: key_type(), Public :: binary()) -> keypair().
|
|
new(Type, Public) ->
|
|
#kp{ type = Type, sec = undefined, pub = Public }.
|
|
|
|
%% @doc Accessor function - return the key type of the key pair.
|
|
-spec key_type(KeyPair :: keypair()) -> key_type().
|
|
key_type(#kp{ type = T }) ->
|
|
T.
|
|
|
|
%% @doc Accessor function - return the public key of the key pair.
|
|
-spec pubkey(KeyPair :: keypair()) -> binary().
|
|
pubkey(#kp{ pub = P }) ->
|
|
P.
|
|
|
|
%% @doc Accessor function - return the secret key of the key pair.
|
|
%% This function will throw an error if the key pair is "public only".
|
|
-spec seckey(KeyPair :: keypair()) -> binary().
|
|
seckey(#kp{ sec = undefined }) ->
|
|
error(keypair_is_public_only);
|
|
seckey(#kp{ sec = S }) ->
|
|
S.
|
|
|
|
%% -- Local functions --------------------------------------------------------
|
|
new_key_pair(dh25519) ->
|
|
KeyPair = enacl:crypto_sign_ed25519_keypair(),
|
|
{enacl:crypto_sign_ed25519_secret_to_curve25519(maps:get(secret, KeyPair)),
|
|
enacl:crypto_sign_ed25519_public_to_curve25519(maps:get(public, KeyPair))};
|
|
new_key_pair(Type) ->
|
|
error({unsupported_key_type, Type}).
|
|
|
|
pubkey_from_secret(dh25519, Secret) ->
|
|
enacl:curve25519_scalarmult_base(Secret).
|