Add secp256k1
This commit is contained in:
parent
864c42ed8c
commit
c739230911
@ -4,7 +4,7 @@
|
||||
{registered, []},
|
||||
{applications, [kernel, stdlib]},
|
||||
{env,[]},
|
||||
{modules, []},
|
||||
{modules, [ecu_secp256k1, ecu_misc]},
|
||||
{licenses, ["MIT"]},
|
||||
{links, []}
|
||||
]}.
|
||||
|
21
src/ecu_misc.erl
Normal file
21
src/ecu_misc.erl
Normal file
@ -0,0 +1,21 @@
|
||||
%%% File : ecu_misc.erl
|
||||
%%% Author : Hans Svensson
|
||||
%%% Description : Misc. functionality
|
||||
%%% Created : 13 Jan 2022 by Hans Svensson
|
||||
-module(ecu_misc).
|
||||
|
||||
-export([eea/2]).
|
||||
|
||||
%% Extended Euclidean Algorithm
|
||||
eea(A, B) when ((A < 1) or (B < 1)) ->
|
||||
undefined;
|
||||
eea(A, B) ->
|
||||
eea(A, 1, 0, B, 0, 1).
|
||||
|
||||
eea(G, S, T, 0, _, _) ->
|
||||
{G, S, T};
|
||||
eea(G0, S0, T0, G1, S1, T1) ->
|
||||
Q = G0 div G1,
|
||||
eea(G1, S1, T1, G0 - (Q * G1), S0 - (Q * S1), T0 - (Q * T1)).
|
||||
|
||||
|
117
src/ecu_secp256k1.erl
Normal file
117
src/ecu_secp256k1.erl
Normal file
@ -0,0 +1,117 @@
|
||||
%%% File : ecu_secp256k1.erl
|
||||
%%% Author : Hans Svensson
|
||||
%%% Description : Trying to whip together a pure Erlang secp256k1
|
||||
%%% Just for usage when speed isn't crucial...
|
||||
%%% Created : 22 Dec 2021 by Hans Svensson
|
||||
-module(ecu_secp256k1).
|
||||
|
||||
-define(P, 16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F).
|
||||
-define(A, 16#00).
|
||||
-define(B, 16#07).
|
||||
-define(X, 16#79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798).
|
||||
-define(Y, 16#483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8).
|
||||
-define(N, 16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141).
|
||||
-define(E, 16#7AE96A2B657C07106E64479EAC3434E99CF0497512F58995C1396C28719501EE).
|
||||
|
||||
-define(ADD(A, B), ((A + B) rem ?P)).
|
||||
-define(MUL(A, B), ((A * B) rem ?P)).
|
||||
-define(SUB(A, B), ((A - B + ?P) rem ?P)).
|
||||
-define(DIV(A, B), f_div(A, B)).
|
||||
|
||||
-export([on_curve/1, p/0, n/0,
|
||||
scalar_mul/2, scalar_mul_base/1, p_add/2, p_neg/1,
|
||||
compress/1, decompress/1,
|
||||
f_add/2, f_mul/2, f_sub/2, f_div/2, f_inv/1,
|
||||
s_add/2, s_mul/2, s_sub/2, s_div/2, s_inv/1]).
|
||||
|
||||
-ifdef(TEST).
|
||||
-compile([export_all, nowarn_export_all]).
|
||||
-endif.
|
||||
|
||||
on_curve({X, Y}) ->
|
||||
%% y^2 = x^3 + 7
|
||||
X3 = ?MUL(?MUL(X, X), X),
|
||||
Y2 = ?MUL(Y, Y),
|
||||
Y2 == ?ADD(X3, ?B).
|
||||
|
||||
p() -> ?P.
|
||||
|
||||
n() -> ?N.
|
||||
|
||||
scalar_mul_base(K) ->
|
||||
scalar_mul(K, {?X, ?Y}).
|
||||
|
||||
scalar_mul(0, _P) ->
|
||||
{0, 0};
|
||||
scalar_mul(1, P) ->
|
||||
P;
|
||||
scalar_mul(K, P) ->
|
||||
case K rem 2 == 0 of
|
||||
true -> scalar_mul(K div 2, p_add(P, P));
|
||||
false -> p_add(P, scalar_mul(K - 1, P))
|
||||
end.
|
||||
|
||||
compress({X, Y}) when Y rem 2 == 0 -> <<2:8, X:256>>;
|
||||
compress({X, _}) -> <<3:8, X:256>>;
|
||||
compress(<<4:8, X:256, Y:256>>) -> compress({X, Y}).
|
||||
|
||||
decompress(<<N:8, X:256>>) ->
|
||||
Y0 = ?B + ?MUL(X, ?MUL(X, X)),
|
||||
Y1 = pow(Y0, (?P + 1) div 4),
|
||||
case Y1 rem 2 == N rem 2 of
|
||||
true -> {X, Y1};
|
||||
false -> {X, ?P - Y1}
|
||||
end.
|
||||
|
||||
p_neg({X, Y}) -> {X, ?P - Y}.
|
||||
|
||||
p_add(P1, {0, 0}) -> P1;
|
||||
p_add({0, 0}, P2) -> P2;
|
||||
p_add({X, Y1}, {X, Y2}) when Y1 /= Y2 -> {0, 0};
|
||||
p_add(P = {X1, Y1}, P) ->
|
||||
M = ?DIV(?MUL(3, ?MUL(X1, X1)), ?MUL(2, Y1)),
|
||||
X3 = ?SUB(?MUL(M, M), ?MUL(2, X1)),
|
||||
Y3 = ?SUB(?MUL(M, ?SUB(X1, X3)), Y1),
|
||||
{X3, Y3};
|
||||
p_add({X1, Y1}, {X2, Y2}) ->
|
||||
M = ?DIV(?SUB(Y2, Y1), ?SUB(X2, X1)),
|
||||
X3 = ?SUB(?MUL(M, M), ?ADD(X1, X2)),
|
||||
Y3 = ?SUB(?MUL(M, ?SUB(X1, X3)), Y1),
|
||||
{X3, Y3}.
|
||||
|
||||
pow(_, 0) -> 1;
|
||||
pow(A, 1) -> A;
|
||||
pow(A, B) -> pow(A, B, 1).
|
||||
|
||||
pow(_, 0, R) -> R;
|
||||
pow(A, B, R) when B rem 2 == 0 -> pow(A * A, B bsr 1, R);
|
||||
pow(A, B, R) -> pow(?MUL(A, A), B bsr 1, ?MUL(R, A)).
|
||||
|
||||
%% Arithmetics in prime field P
|
||||
f_add(A, B) -> (A + B) rem ?P.
|
||||
f_mul(A, B) -> (A * B) rem ?P.
|
||||
f_sub(A, B) -> (A - B + ?P) rem ?P.
|
||||
f_div(A, B) -> f_mul(A, f_inv(B)).
|
||||
|
||||
f_inv(A) ->
|
||||
{1, S, _T} = ecu_misc:eea(A, ?P),
|
||||
(S + ?P) rem ?P.
|
||||
|
||||
%% Arithmetics in curve group order N
|
||||
s_add(A, B) -> (A + B) rem ?N.
|
||||
s_mul(A, B) -> (A * B) rem ?N.
|
||||
s_sub(A, B) -> (A - B + ?N) rem ?N.
|
||||
s_div(A, B) -> s_mul(A, s_inv(B)).
|
||||
|
||||
s_inv(A) ->
|
||||
{1, S, _T} = ecu_misc:eea(A, ?N),
|
||||
(S + ?N) rem ?N.
|
||||
|
||||
%% curve() ->
|
||||
%% #{ p => 16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F,
|
||||
%% a => 16#00, b => 16#07,
|
||||
%% x => 16#79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,
|
||||
%% y => 16#483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8,
|
||||
%% n => 16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,
|
||||
%% e => 16#7AE96A2B657C07106E64479EAC3434E99CF0497512F58995C1396C28719501EE
|
||||
%% }.
|
73
test/secp256k1_tests.erl
Normal file
73
test/secp256k1_tests.erl
Normal file
@ -0,0 +1,73 @@
|
||||
%%% File : secp256k1_tests.erl
|
||||
%%% Author : Hans Svensson
|
||||
%%% Description :
|
||||
%%% Created : 22 Dec 2021 by Hans Svensson
|
||||
-module(secp256k1_tests).
|
||||
|
||||
-compile([export_all, nowarn_export_all]).
|
||||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
on_curve_test() ->
|
||||
%% https://chuckbatson.wordpress.com/2014/11/26/secp256k1-test-vectors/
|
||||
KnownPts =
|
||||
[{16#79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,
|
||||
16#483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8},
|
||||
{16#C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5,
|
||||
16#1AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A},
|
||||
{16#F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9,
|
||||
16#388F7B0F632DE8140FE337E62A37F3566500A99934C2231B6CB9FD7584B8E672},
|
||||
{16#E493DBF1C10D80F3581E4904930B1404CC6C13900EE0758474FA94ABE8C4CD13,
|
||||
16#51ED993EA0D455B75642E2098EA51448D967AE33BFBDFE40CFE97BDC47739922},
|
||||
{16#2F8BDE4D1A07209355B4A7250A5C5128E88B84BDDC619AB7CBA8D569B240EFE4,
|
||||
16#D8AC222636E5E3D6D4DBA9DDA6C9C426F788271BAB0D6840DCA87D3AA6AC62D6}],
|
||||
|
||||
[ ?assert(ecu_secp256k1:on_curve(Pt)) || Pt <- KnownPts ],
|
||||
|
||||
?assert(not ecu_secp256k1:on_curve({42, 723})).
|
||||
|
||||
scalar_mul_test() ->
|
||||
%% https://chuckbatson.wordpress.com/2014/11/26/secp256k1-test-vectors/
|
||||
KnownPts =
|
||||
[{1,
|
||||
16#79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,
|
||||
16#483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8},
|
||||
{2,
|
||||
16#C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5,
|
||||
16#1AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A},
|
||||
{3,
|
||||
16#F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9,
|
||||
16#388F7B0F632DE8140FE337E62A37F3566500A99934C2231B6CB9FD7584B8E672},
|
||||
{4,
|
||||
16#E493DBF1C10D80F3581E4904930B1404CC6C13900EE0758474FA94ABE8C4CD13,
|
||||
16#51ED993EA0D455B75642E2098EA51448D967AE33BFBDFE40CFE97BDC47739922},
|
||||
{5,
|
||||
16#2F8BDE4D1A07209355B4A7250A5C5128E88B84BDDC619AB7CBA8D569B240EFE4,
|
||||
16#D8AC222636E5E3D6D4DBA9DDA6C9C426F788271BAB0D6840DCA87D3AA6AC62D6},
|
||||
{20,
|
||||
16#4CE119C96E2FA357200B559B2F7DD5A5F02D5290AFF74B03F3E471B273211C97,
|
||||
16#12BA26DCB10EC1625DA61FA10A844C676162948271D96967450288EE9233DC3A},
|
||||
{112233445566778899,
|
||||
16#A90CC3D3F3E146DAADFC74CA1372207CB4B725AE708CEF713A98EDD73D99EF29,
|
||||
16#5A79D6B289610C68BC3B47F3D72F9788A26A06868B4D8E433E1E2AD76FB7DC76},
|
||||
{112233445566778899112233445566778899,
|
||||
16#E5A2636BCFD412EBF36EC45B19BFB68A1BC5F8632E678132B885F7DF99C5E9B3,
|
||||
16#736C1CE161AE27B405CAFD2A7520370153C2C861AC51D6C1D5985D9606B45F39}
|
||||
],
|
||||
|
||||
[ begin
|
||||
{X, Y} = ecu_secp256k1:scalar_mul_base(K),
|
||||
?assertEqual({x, K, Ex}, {x, K, X}),
|
||||
?assertEqual({y, K, Ey}, {y, K, Y})
|
||||
end || {K, Ex, Ey} <- KnownPts ].
|
||||
|
||||
compression_test() ->
|
||||
Test = fun(P) ->
|
||||
CP = ecu_secp256k1:compress(P),
|
||||
DP = ecu_secp256k1:decompress(CP),
|
||||
%% ?debugFmt("\nP : ~200p\nCP: ~200p\nDP: ~200p", [P, CP, DP]),
|
||||
?assertEqual(P, DP)
|
||||
end,
|
||||
[ Test(ecu_secp256k1:scalar_mul_base(K)) || K <- lists:seq(10, 100) ].
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user