Skip to content

Commit

Permalink
Merge pull request #71 from helium/sk/remove-pbc-compatibility
Browse files Browse the repository at this point in the history
Remove PBC based cryptography
  • Loading branch information
evanmcc authored Jul 21, 2021
2 parents db7af6a + 60579e6 commit d252363
Show file tree
Hide file tree
Showing 12 changed files with 212 additions and 547 deletions.
1 change: 0 additions & 1 deletion rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
{cover_enabled, true}.
{deps, [
{erlang_tc, ".*", {git, "https://github.com/helium/erlang-tc.git", {branch, "main"}}},
{erlang_tpke, ".*", {git, "https://github.com/helium/erlang-tpke.git", {branch, "master"}}},
{erasure, {git, "https://github.com/helium/erlang-erasure.git", {branch, "master"}}},
{merkerl, "1.0.1"}
]}.
Expand Down
8 changes: 0 additions & 8 deletions rebar.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,10 @@
{git,"https://github.com/helium/erlang-erasure.git",
{ref,"c73354ca9914225a825569693dc72db6691d91f1"}},
0},
{<<"erlang_pbc">>,
{git,"https://github.com/helium/erlang_pbc.git",
{ref,"1d2651ba01ba81b748c553d9f729c0e167eeab72"}},
1},
{<<"erlang_tc">>,
{git,"https://github.com/helium/erlang-tc.git",
{ref,"b3ef1d5541586f5c85b6d231345a921d57be32a3"}},
0},
{<<"erlang_tpke">>,
{git,"https://github.com/helium/erlang-tpke.git",
{ref,"02e955cd16ca31519b1b9aaf46cf98ddc406b469"}},
0},
{<<"merkerl">>,{pkg,<<"merkerl">>,<<"1.0.1">>},0}]}.
[
{pkg_hash,[
Expand Down
1 change: 0 additions & 1 deletion src/hbbft.app.src
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
stdlib,
merkerl,
erlang_tc,
erlang_tpke,
erasure
]},
{env,[]},
Expand Down
376 changes: 104 additions & 272 deletions src/hbbft.erl

Large diffs are not rendered by default.

113 changes: 41 additions & 72 deletions src/hbbft_cc.erl
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

-record(cc_data, {
state = waiting :: waiting | done,
sk :: tc_key_share:tc_key_share() | tpke_privkey:privkey(),
sk :: tc_key_share:tc_key_share(),
%% Note: sid is assumed to be a unique nonce that serves as name of this common coin
sid :: binary() | erlang_pbc:element(),
sid :: binary(),
n :: pos_integer(),
f :: non_neg_integer(),
shares = maps:new() :: #{non_neg_integer() => {non_neg_integer(), tc_signature_share:sig_share()}}
Expand All @@ -32,7 +32,7 @@ status(undefined) ->
undefined;
status(CCData) ->
#{state => CCData#cc_data.state,
shares => serialize_shares(hbbft_utils:curve(CCData#cc_data.sk), CCData#cc_data.shares)
shares => serialize_shares(CCData#cc_data.shares)
}.

%% Figure12. Bullet1
Expand All @@ -45,30 +45,18 @@ status(CCData) ->
binary(),
pos_integer(),
non_neg_integer()) -> cc_data().
init(KeyShare, Sid0, N, F) ->
Sid = case tc_key_share:is_key_share(KeyShare) of
true ->
Sid0;
false ->
tpke_pubkey:hash_message(tpke_privkey:public_key(KeyShare), Sid0)
end,
init(KeyShare, Sid, N, F) ->
true = tc_key_share:is_key_share(KeyShare),
#cc_data{sk=KeyShare, n=N, f=F, sid=Sid}.

%% Figure12. Bullet2
%% on input GetCoin, multicast ThresholdSignpk (ski, sid)
-spec get_coin(cc_data()) -> {cc_data(), ok | {send, [hbbft_utils:multicast(share_msg())]}}.
get_coin(Data = #cc_data{state=done}) ->
{Data, ok};
get_coin(Data = #cc_data{sk=SK}) ->
case hbbft_utils:curve(SK) of
'BLS12-381' ->
Share = tc_key_share:sign_share(Data#cc_data.sk, Data#cc_data.sid),
{Data, {send, [{multicast, {share, hbbft_utils:sig_share_to_binary('BLS12-381', Share)}}]}};
'SS512' ->
Share = tpke_privkey:sign(Data#cc_data.sk, Data#cc_data.sid),
SerializedShare = hbbft_utils:sig_share_to_binary('SS512', Share),
{Data, {send, [{multicast, {share, SerializedShare}}]}}
end.
get_coin(Data = #cc_data{}) ->
Share = tc_key_share:sign_share(Data#cc_data.sk, Data#cc_data.sid),
{Data, {send, [{multicast, {share, hbbft_utils:sig_share_to_binary(Share)}}]}}.


%% upon receiving at least f + 1 shares, attempt to combine them
Expand All @@ -87,16 +75,13 @@ share(#cc_data{state=done}, _J, _Share) ->
share(Data=#cc_data{sk=SK}, J, Share) ->
case maps:is_key(J, Data#cc_data.shares) of
false ->
Curve = hbbft_utils:curve(SK),
DeserializedShare = hbbft_utils:binary_to_sig_share(Curve, SK, Share),
ValidShare = case Curve of
'BLS12-381' ->
tc_key_share:verify_signature_share(Data#cc_data.sk,
DeserializedShare,
Data#cc_data.sid);
'SS512' ->
tpke_pubkey:verify_signature_share(tpke_privkey:public_key(Data#cc_data.sk), DeserializedShare, Data#cc_data.sid)
end,
DeserializedShare = hbbft_utils:binary_to_sig_share(Share),
ValidShare =
tc_key_share:verify_signature_share(
Data#cc_data.sk,
DeserializedShare,
Data#cc_data.sid
),
case ValidShare of
true ->
%% store the deserialized share in the shares map, convenient to use later to verify signature
Expand All @@ -105,26 +90,22 @@ share(Data=#cc_data{sk=SK}, J, Share) ->
case maps:size(NewData#cc_data.shares) > Data#cc_data.f of
true ->
%% combine shares
{ok, Sig} = case Curve of
'BLS12-381' ->
tc_key_share:combine_signature_shares(SK, maps:values(NewData#cc_data.shares));
'SS512' ->
tpke_pubkey:combine_verified_signature_shares(tpke_privkey:public_key(NewData#cc_data.sk), maps:values(NewData#cc_data.shares))
end,
{ok, Sig} =
tc_key_share:combine_signature_shares(
SK,
maps:values(NewData#cc_data.shares)
),
%% check if the signature is valid
ValidSignature = case Curve of
'BLS12-381' ->
tc_key_share:verify(NewData#cc_data.sk, Sig, NewData#cc_data.sid);
'SS512' ->
tpke_pubkey:verify_signature(tpke_privkey:public_key(NewData#cc_data.sk), Sig, NewData#cc_data.sid)
end,
case ValidSignature of
case
tc_key_share:verify(
NewData#cc_data.sk,
Sig,
NewData#cc_data.sid
)
of
true ->
%% TODO do something better here!
<<Val:32/integer, _/binary>> = case Curve of
'BLS12-381' -> tc_signature:serialize(Sig);
'SS512' -> erlang_pbc:element_to_binary(Sig)
end,
<<Val:32/integer, _/binary>> = tc_signature:serialize(Sig),
{NewData#cc_data{state=done}, {result, Val}};
false ->
{NewData, ok}
Expand All @@ -141,43 +122,31 @@ share(Data=#cc_data{sk=SK}, J, Share) ->
end.

-spec serialize(cc_data()) -> cc_serialized_data().
serialize(#cc_data{state = State, sid = SID, n = N, sk = SK, f = F, shares = Shares}) ->
serialize(#cc_data{state = State, sid = <<SID/binary>>, n = N, f = F, shares = Shares}) ->
#cc_serialized_data{
state = State,
sid = serialize_sid(SID),
sid = SID,
n = N,
f = F,
shares = serialize_shares(hbbft_utils:curve(SK), Shares)
shares = serialize_shares(Shares)
}.

-spec deserialize(cc_serialized_data(), tc_key_share:tc_key_share() | tpke_privkey:privkey()) ->
-spec deserialize(cc_serialized_data(), tc_key_share:tc_key_share()) ->
cc_data().
deserialize(#cc_serialized_data{state = State, sid = SID, n = N, f = F, shares = Shares}, SK) ->
deserialize(#cc_serialized_data{state = State, sid = <<SID/binary>>, n = N, f = F, shares = Shares}, SK) ->
#cc_data{
state = State,
sk = SK,
sid = deserialize_sid(SK, SID),
sid = SID,
n = N,
f = F,
shares = deserialize_shares(hbbft_utils:curve(SK), SK, Shares)
shares = deserialize_shares(Shares)
}.

-spec serialize_shares('BLS12-381' | 'SS512', #{non_neg_integer() => tc_signature_share:sig_share()}) -> #{non_neg_integer() => binary()}.
serialize_shares(Curve, Shares) ->
maps:map(fun(_K, V) -> hbbft_utils:sig_share_to_binary(Curve, V) end, Shares).

-spec deserialize_shares('BLS12-381' | 'SS512', tc_key_share:tc_key_share() | tpke_privkey:privkey(), #{non_neg_integer() => binary()}) -> #{non_neg_integer() => tc_signature_share:sig_share()}.
deserialize_shares(Curve, SK, Shares) ->
maps:map(fun(_K, V) -> hbbft_utils:binary_to_sig_share(Curve, SK, V) end, Shares).

serialize_sid(SID) when is_binary(SID) ->
SID;
serialize_sid(SID) ->
erlang_pbc:element_to_binary(SID).

deserialize_sid(SK, SID) ->
case hbbft_utils:curve(SK) of
'BLS12-381' -> SID;
'SS512' -> tpke_pubkey:deserialize_element(tpke_privkey:public_key(SK), SID)
end.
-spec serialize_shares(#{non_neg_integer() => tc_signature_share:sig_share()}) -> #{non_neg_integer() => binary()}.
serialize_shares(Shares) ->
maps:map(fun(_K, V) -> hbbft_utils:sig_share_to_binary(V) end, Shares).

-spec deserialize_shares(#{non_neg_integer() => binary()}) -> #{non_neg_integer() => tc_signature_share:sig_share()}.
deserialize_shares(Shares) ->
maps:map(fun(_K, V) -> hbbft_utils:binary_to_sig_share(V) end, Shares).
46 changes: 12 additions & 34 deletions src/hbbft_utils.erl
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,32 @@
-export_type([unicast/1, multicast/1]).

-export([
sig_share_to_binary/2,
binary_to_sig_share/3,
dec_share_to_binary/2,
binary_to_dec_share/3,
sig_share_to_binary/1,
binary_to_sig_share/1,
dec_share_to_binary/1,
binary_to_dec_share/1,
wrap/2,
random_n/2,
shuffle/1,
curve/1
shuffle/1
]).

sig_share_to_binary('BLS12-381', {ShareIdx, SigShare}) ->
sig_share_to_binary({ShareIdx, SigShare}) ->
%% Assume less than 256 members in the consensus group
ShareBinary = tc_signature_share:serialize(SigShare),
<<ShareIdx:8/integer-unsigned, ShareBinary/binary>>;
sig_share_to_binary('SS512', {ShareIdx, SigShare}) ->
ShareBinary = erlang_pbc:element_to_binary(SigShare),
<<ShareIdx:8/integer-unsigned, ShareBinary/binary>>.

binary_to_sig_share('BLS12-381', _SK, <<ShareIdx:8/integer-unsigned, ShareBinary/binary>>) ->
binary_to_sig_share(<<ShareIdx:8/integer-unsigned, ShareBinary/binary>>) ->
SigShare = tc_signature_share:deserialize(ShareBinary),
{ShareIdx, SigShare};
binary_to_sig_share('SS512', SK, <<ShareIdx:8/integer-unsigned, ShareBinary/binary>>) ->
ShareElement = tpke_pubkey:deserialize_element(tpke_privkey:public_key(SK), ShareBinary),
{ShareIdx, ShareElement}.
{ShareIdx, SigShare}.

dec_share_to_binary('BLS12-381', {ShareIdx, DecShare}) ->
dec_share_to_binary({ShareIdx, DecShare}) ->
%% Assume less than 256 members in the consensus group
ShareBinary = tc_decryption_share:serialize(DecShare),
<<ShareIdx:8/integer-unsigned, ShareBinary/binary>>;
dec_share_to_binary('SS512', {ShareIdx, DecShare}) ->
%% Assume less than 256 members in the consensus group
ShareBinary = erlang_pbc:element_to_binary(DecShare),
<<ShareIdx:8/integer-unsigned, ShareBinary/binary>>.

binary_to_dec_share('BLS12-381', _SK, <<ShareIdx:8/integer-unsigned, ShareBinary/binary>>) ->
binary_to_dec_share(<<ShareIdx:8/integer-unsigned, ShareBinary/binary>>) ->
DecShare = tc_decryption_share:deserialize(ShareBinary),
{ShareIdx, DecShare};
binary_to_dec_share('SS512', SK, <<ShareIdx:8/integer-unsigned, ShareBinary/binary>>) ->
ShareElement = tpke_pubkey:deserialize_element(tpke_privkey:public_key(SK), ShareBinary),
{ShareIdx, ShareElement}.
{ShareIdx, DecShare}.

%% wrap a subprotocol's outbound messages with a protocol identifier
-spec wrap(Tag :: atom() | {atom(), non_neg_integer()}, [{multicast, Msg :: any()} | {unicast, non_neg_integer(), Msg :: any()}]) -> [{multicast, {Tag, Msg}} | {unicast, non_neg_integer(), {Tag, Msg}}].
Expand All @@ -60,15 +46,7 @@ wrap(Id, [{unicast, Dest, Msg}|T]) ->
random_n(N, List) ->
lists:sublist(shuffle(List), N).

%% FIXME Assumes numeric list - update spec or replace with generic shuffle.
-spec shuffle(list()) -> list().
shuffle(List) ->
[X || {_,X} <- lists:sort([{rand:uniform(), N} || N <- List])].

-spec curve(KeyShare :: hbbft:key_share()) -> hbbft:curve().
curve(KeyShare) ->
case tc_key_share:is_key_share(KeyShare) of
true ->
'BLS12-381';
false ->
'SS512'
end.
Loading

0 comments on commit d252363

Please sign in to comment.