summaryrefslogtreecommitdiff
path: root/src/r3_hex_registry.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/r3_hex_registry.erl')
-rw-r--r--src/r3_hex_registry.erl133
1 files changed, 133 insertions, 0 deletions
diff --git a/src/r3_hex_registry.erl b/src/r3_hex_registry.erl
new file mode 100644
index 0000000..86f9176
--- /dev/null
+++ b/src/r3_hex_registry.erl
@@ -0,0 +1,133 @@
+%% Vendored from hex_core v0.5.0, do not edit manually
+
+-module(r3_hex_registry).
+-export([
+ encode_names/1,
+ decode_names/2,
+ encode_versions/1,
+ decode_versions/2,
+ encode_package/1,
+ decode_package/3,
+ sign_protobuf/2,
+ decode_signed/1,
+ decode_and_verify_signed/2,
+ sign/2,
+ verify/3
+]).
+-include_lib("public_key/include/public_key.hrl").
+
+-type private_key() :: public_key:rsa_private_key() | binary().
+-type public_key() :: public_key:rsa_public_key() | binary().
+
+%%====================================================================
+%% API functions
+%%====================================================================
+
+%% @doc
+%% Encode Names message.
+encode_names(Names) ->
+ r3_hex_pb_names:encode_msg(Names, 'Names').
+
+%% @doc
+%% Decode message created with encode_names/1.
+decode_names(Payload, no_verify) ->
+ #{packages := Packages} = r3_hex_pb_names:decode_msg(Payload, 'Names'),
+ {ok, Packages};
+
+decode_names(Payload, Repository) ->
+ case r3_hex_pb_names:decode_msg(Payload, 'Names') of
+ #{repository := Repository, packages := Packages} ->
+ {ok, Packages};
+ _ ->
+ {error, unverified}
+ end.
+
+%% @doc
+%% Encode Versions message.
+encode_versions(Versions) ->
+ r3_hex_pb_versions:encode_msg(Versions, 'Versions').
+
+%% @doc
+%% Decode message created with encode_versions/1.
+decode_versions(Payload, no_verify) ->
+ #{packages := Packages} = r3_hex_pb_versions:decode_msg(Payload, 'Versions'),
+ {ok, Packages};
+
+decode_versions(Payload, Repository) ->
+ case r3_hex_pb_versions:decode_msg(Payload, 'Versions') of
+ #{repository := Repository, packages := Packages} ->
+ {ok, Packages};
+ _ ->
+ {error, unverified}
+ end.
+
+%% @doc
+%% Encode Package message.
+encode_package(Package) ->
+ r3_hex_pb_package:encode_msg(Package, 'Package').
+
+%% @doc
+%% Decode message created with encode_package/1.
+decode_package(Payload, no_verify, no_verify) ->
+ #{releases := Releases} = r3_hex_pb_package:decode_msg(Payload, 'Package'),
+ {ok, Releases};
+
+decode_package(Payload, Repository, Package) ->
+ case r3_hex_pb_package:decode_msg(Payload, 'Package') of
+ #{repository := Repository, name := Package, releases := Releases} ->
+ {ok, Releases};
+ _ ->
+ {error, unverified}
+ end.
+
+%% @doc
+%% Encode Signed message.
+sign_protobuf(Payload, PrivateKey) ->
+ Signature = sign(Payload, PrivateKey),
+ r3_hex_pb_signed:encode_msg(#{payload => Payload, signature => Signature}, 'Signed').
+
+%% @doc
+%% Decode message created with sign_protobuf/2 without verification.
+decode_signed(Signed) ->
+ r3_hex_pb_signed:decode_msg(Signed, 'Signed').
+
+%% @doc
+%% Decode message created with sign_protobuf/2 and verify it against public key.
+-spec decode_and_verify_signed(map(), public_key()) -> {ok, binary()} | {error, term()}.
+decode_and_verify_signed(Signed, PublicKey) ->
+ #{payload := Payload, signature := Signature} = decode_signed(Signed),
+ case verify(Payload, Signature, PublicKey) of
+ true -> {ok, Payload};
+ false -> {error, unverified};
+ {error, Reason} -> {error, Reason}
+ end.
+
+%% @doc
+%% Signs binary with given private key.
+-spec sign(binary(), private_key()) -> binary().
+sign(Binary, PrivateKey) ->
+ {ok, RSAPrivateKey} = key(PrivateKey),
+ public_key:sign(Binary, sha512, RSAPrivateKey).
+
+%% @doc
+%% Verifies binary against signature and a public key.
+-spec verify(binary(), binary(), public_key()) -> boolean() | {error, term()}.
+verify(Binary, Signature, PublicKey) ->
+ case key(PublicKey) of
+ {ok, RSAPublicKey} -> public_key:verify(Binary, sha512, Signature, RSAPublicKey);
+ {error, Reason} -> {error, Reason}
+ end.
+
+%%====================================================================
+%% Internal functions
+%%====================================================================
+
+key(#'RSAPublicKey'{} = Key) ->
+ {ok, Key};
+key(#'RSAPrivateKey'{} = Key) ->
+ {ok, Key};
+key(Binary) when is_binary(Binary) ->
+ case public_key:pem_decode(Binary) of
+ [Entry | _] -> {ok, public_key:pem_entry_decode(Entry)};
+ _ -> {error, bad_key}
+ end.