Better ecu_crypto API + ec_recover/2
This commit is contained in:
parent
5a0d41bd62
commit
0dad93cf3c
@ -5,7 +5,9 @@
|
||||
-module(ecu_crypto).
|
||||
|
||||
-export([private_to_short/2, public_to_short/2,
|
||||
eth_sign/2, eth_recover/2, eth_verify/3, eth_msg_hash/1,
|
||||
ec_recover/2,
|
||||
eth_sign/2, eth_recover/2, eth_verify/3,
|
||||
eth_msg_sign/2, eth_msg_recover/2, eth_msg_verify/3, eth_msg_hash/1,
|
||||
keccak256/1]).
|
||||
|
||||
private_to_short(bitcoin, PrivateKey) ->
|
||||
@ -26,15 +28,33 @@ public_to_short(ethereum, PubKey) ->
|
||||
ShortPub
|
||||
end.
|
||||
|
||||
eth_msg_sign(Msg, PrivateKey = <<_:32/bytes>>) ->
|
||||
eth_sign(eth_msg_hash(Msg), PrivateKey).
|
||||
|
||||
eth_sign(Msg, PrivateKey = <<_:32/bytes>>) ->
|
||||
{BaseSig, YVal} = ecu_ecdsa:sign_secp256k1(eth_msg_hash(Msg), PrivateKey),
|
||||
{BaseSig, YVal} = ecu_ecdsa:sign_secp256k1(Msg, PrivateKey),
|
||||
V = if YVal rem 2 == 0 -> 27;
|
||||
true -> 28
|
||||
end,
|
||||
<<V:8, BaseSig/bytes>>.
|
||||
|
||||
eth_recover(Msg, Sig = <<_:65/bytes>>) ->
|
||||
MsgHash = eth_msg_hash(Msg),
|
||||
eth_msg_recover(Msg, Sig = <<_:65/bytes>>) ->
|
||||
eth_recover(eth_msg_hash(Msg), Sig).
|
||||
|
||||
%% This is the mythical Ethereum ECRECOVERY operation
|
||||
ec_recover(MsgHash = <<_:32/bytes>>, Sig = <<_:65/bytes>>) ->
|
||||
<<V:8, R:256, S:256>> = Sig,
|
||||
case (V == 27 orelse V == 28) andalso
|
||||
(R >= 1 andalso R =< ecu_secp256k1:n()) andalso
|
||||
(S >= 1 andalso S =< ecu_secp256k1:n()) of
|
||||
true ->
|
||||
ShortPub = eth_recover(MsgHash, Sig),
|
||||
<<0:96, ShortPub/binary>>;
|
||||
false ->
|
||||
<<0:256>>
|
||||
end.
|
||||
|
||||
eth_recover(MsgHash = <<_:32/bytes>>, Sig = <<_:65/bytes>>) ->
|
||||
<<E:256>> = MsgHash,
|
||||
<<V:8, R:256, S:256>> = Sig,
|
||||
Z = E rem ecu_secp256k1:n(),
|
||||
@ -49,8 +69,11 @@ eth_recover(Msg, Sig = <<_:65/bytes>>) ->
|
||||
<<_:12/bytes, RPub:20/bytes>> = keccak256(<<X:256, Y:256>>),
|
||||
RPub.
|
||||
|
||||
eth_verify(Msg, PublicKey, Sig) ->
|
||||
PublicKey == eth_recover(Msg, Sig).
|
||||
eth_msg_verify(Msg, PublicKey, Sig) ->
|
||||
eth_verify(eth_msg_hash(Msg), PublicKey, Sig).
|
||||
|
||||
eth_verify(Msg, PublickKey, Sig) ->
|
||||
PublickKey == eth_recover(Msg, Sig).
|
||||
|
||||
eth_msg_hash(Msg0) ->
|
||||
Msg = ["\x19Ethereum Signed Message:\n", integer_to_list(byte_size(Msg0)), Msg0],
|
||||
|
@ -20,16 +20,16 @@ eth_sign_verify_test() ->
|
||||
Data = [{Pr, ecu_crypto:private_to_short(ethereum, Pr), M} || {Pr, M} <- Data0],
|
||||
|
||||
Test = fun(PrivK, PubK, MsgHash) ->
|
||||
Sig = ecu_crypto:eth_sign(MsgHash, PrivK),
|
||||
?assertEqual(PubK, ecu_crypto:eth_recover(MsgHash, Sig))
|
||||
Sig = ecu_crypto:eth_msg_sign(MsgHash, PrivK),
|
||||
?assertEqual(PubK, ecu_crypto:eth_msg_recover(MsgHash, Sig))
|
||||
end,
|
||||
|
||||
{T, _} = timer:tc(fun() -> [ Test(Pr, Pu, M) || {Pr, Pu, M} <- Data ] end),
|
||||
?debugFmt("Average time for eth_sign+eth_recovery: ~.3f ms", [(T / 1000) / length(Data)]).
|
||||
?debugFmt("Average time for eth_msg_sign+eth_msg_recovery: ~.3f ms", [(T / 1000) / length(Data)]).
|
||||
|
||||
recover_test() ->
|
||||
<<R:256, S:256>> = ecu_misc:hex_to_bin("a5f270865420c8595128cf7132dcedb1221abf89286f926d067dff2fa59347c07a0fd06e8b4a567b0628a01d5398480a49c540c0cbd9980abd08cf3818f25e2e"),
|
||||
%% <<Priv:256>> = hex_to_bin("9a4a5c038e7ce00f0ad216894afc00de6b41bbca1d4d7742104cb9f078c6d2df"),
|
||||
%% <<Z:256>> = hex_to_bin("4a5c5d454721bbbb25540c3317521e71c373ae36458f960d2ad46ef088110e95"), %% MsgHash
|
||||
ShortPub = ecu_misc:hex_to_bin("E53e2125F377D5c62a1FfbfEEB89A0826E9dE54C"),
|
||||
?assertEqual(ShortPub, ecu_crypto:eth_recover(<<"test">>, <<28:8, R:256, S:256>>)).
|
||||
?assertEqual(ShortPub, ecu_crypto:eth_msg_recover(<<"test">>, <<28:8, R:256, S:256>>)).
|
||||
|
Loading…
x
Reference in New Issue
Block a user