Skip to content

Instantly share code, notes, and snippets.

@rdm
Created January 31, 2014 14:41
Show Gist options
  • Save rdm/8733290 to your computer and use it in GitHub Desktop.
Save rdm/8733290 to your computer and use it in GitHub Desktop.
cocurrent 'CurveFp'
Help=: 'Elliptic Curve over the field of integers modulo a prime.'
create=:3 :0
NB. The curve of points satisfying y^2 = x^3 + a*x + b (mod p).
'P A B'=: x:&> y
poly=: B,A,0,1
)
p=:3 :'P'
a=:3 :'A'
b=:3 :'B'
containsPoint=:4 :0
0 = P|(0 0 1 p. y) - poly p. x
)
cocurrent 'Point'
Help=:'A point on an elliptic curve'
create=:3 :0
This=: coname''
'Curve X Y Order'=: args=. 4{.y,<'' assert. (#y) e. 3 4
ORDERED=: -. '' -: 3 {:: args
if.#Curve do.
NB. assert. X containsPoint__Curve Y
end.
if. ORDERED do.
assert. infinite mul__This Order
end.
)
infinite=:3 :0
(''-:Curve__y)*.(''-:X__y)*.''-:Y__y
)
invmod=: 4 : 0
NB. inverse of y mod x (x|y)
NB. uc vc ud vd d c where d c init as x y
NB. q =. d<.@%c -- (4&{ <.@%~ {:)
a=. imw^:_ ] 1x,0x,0x,1x,x,y
if. 1~: 4{a do. 0 return. end.
if.0< 2{ a do. 2{ a else. x+2{a end.
)
imw =: ((2&{ - {. * 4&{ <.@% {:),(3&{ - 1&{ * 4&{ <.@% {:), 2&{., ({: | 4&{) ,~{:)^:(0 ~: {:)
eq=:3 :0
if. #cy=. Curve__y do.
if.-.#Curve do. 0 return. end.
if. A__Curve ~: A__cy do. 0 return. end.
if. B__Curve ~: B__cy do. 0 return. end.
if. P__Curve ~: P__cy do. 0 return. end.
else. if. #Curve do. 0 return. end.
end.
(xy'')-: xy__y''
)
add=:3 :0
NB. add another point to this point
if. infinite y do. This return. end. NB. infinity is the new zero
if. infinite This do. y return. end.
assert. Curve -: Curve__y NB. can only add points on same curve
p=. p__Curve'' NB. add
if. X = X__y do.
if. 0 = p | Y + Y__y do.
INFINITY return.
else.
double'' return.
end.
end.
l=. p | (Y__y - Y) * p invmod X__y-X
x3=. p | (0 0 1 p. l) - X+X__y
y3=. p | (l * (X - x3)) - Y
(Curve; x3; y3) conew 'Point' return.
)
leftmostBit=: </\&.#:
bitAnd=: *./@,:&.|.&.#:
mul=: 3 :0
e=. y
if. ORDERED do. e=. Order|e end.
if. 0 = e do. INFINITY return. end.
if. infinite This do. INFINITY return. end.
assert. e > 0
e3=. e*3
negativeSelf=. (Curve;X;(-Y);Order) conew 'Point'
i =. leftmostBit e3
result=. This
while. 1 < i=. <. -: i do.
result=. double__result''
if. (0 ~: e3 bitAnd i) *. (0 = e bitAnd i) do. result=. add__This result end.
if. (0 = e3 bitAnd i) *. (0 ~: e bitAnd i) do. result=. add__negativeSelf result end.
end.
)
str=:3 :0
if. infinite This do. 'infinity' return. end.
'(',(":X),',',(":Y),')'
)
double=:3 :0
NB. Return a new point that is twice this one
if. infinite This do. INFINITY return. end.
p=. p__Curve''
a=. a__Curve''
l=. p | ((a,0,3) p. X) * p invmod 2*Y
x3=. p | (l*l) - 2*X
y3=. p | (l*(X-x3)) - Y
(Curve; x3; y3) conew 'Point'
)
x0=: 3 :'X'
y0=: 3 :'Y'
xy=: 3 :'X,Y'
curve=: 3 :'Curve'
order=: 3 :'Order'
INFINITY=: ('';'';'') conew 'Point'
cocurrent 'test'
test_add=: 3 :0
'c x1 y1 x2 y2 x3 y3'=: y
p1=. (c;x1;y1) conew 'Point'
p2=. (c;x2;y2) conew 'Point'
p3=. add__p1 p2
prefix=. (str__p1''),' + ',(str__p2''),' = ',(str__p3''),' '
if. (x3 ~: x0__p3'') +. (y3 ~: y0__p3'') do.
smoutput prefix,'Failure: should give (',(":x3),',',(":y3),')'
else.
smoutput prefix,' Good.'
end.
)
test_double=: 3 :0
NB. We expect that on curve c, 2*(x1,y1) = (x3, y3).
'c x1 y1 x3 y3'=: y
p1=. (c;x1;y1) conew 'Point'
p3=. double__p1''
prefix=. (str__p1''),' doubled = ',(str__p3''),' '
if. (x3 ~: x0__p3'') +. y3 ~: y0__p3'' do.
smoutput prefix,'Failure: should give (',(":x3),',',(":y3),').'
else.
smoutput prefix,' Good.'
end.
)
test_double_infinity=: 3 :0
NB. We expect that on curve c, 2*INFINITY = INFINITY.
p1=. INFINITY_Point_
p3=. double__p1''
prefix=: (str__p1''),' doubled = ',(str__p3''),' '
if. -. (xy__p1'') -: xy__p3'' do.
smoutput prefix,'Failure: should give (',(":x0__p1''),',',(":y0__p1''),').'
else.
smoutput prefix,' Good.'
end.
)
test_multiply=: 3 :0
'c x1 y1 m x3 y3'=: y
p1=. (c;x1;y1) conew 'Point'
p3=. mul__p1 m
prefix=. (str__p1''),' * ',(":m),' = ',(str__p3''),' '
if. (x3 ~: x0__p3'') +. (y3 ~: y0__p3'') do.
smoutput prefix,'Failure: should give (',(":x3),',',(":y3),')'
else.
smoutput prefix,' Good.'
end.
)
main=:3 :0
c=. (23;1;1) conew 'CurveFp'
test_add c;3;10;9;7;17;20
test_double c;3;10;7;12
test_add c;3;10;3;10;7;12
test_multiply c;3;10;2;7;12
test_double_infinity c
g=. (c;13;7;7) conew 'Point'
check=. INFINITY_Point_
for_i. i. 7+1 do.
p=. mul__g 7 | i
prefix=. (str__g''),' * ',(":i),' = ',(str__p''),', expected ',(str__check''),' . . . '
if. eq__p check do.
smoutput prefix,' Good.'
else.
smoutput prefix,'Bad.'
end.
check=. add__check g
end.
p=. 6277101735386680763835789423207666416083908700390324961279x
r=. 6277101735386680763835789423176059013767194773182842284081x
dfhx=. 16x #. 16 | '0123456789ABCDEF0123456789abcdef' i. ]
c=. dfhx '3099d2bbbfcb2538542dcd5fb078b6ef5f3d6fe2c745de65'
b=. dfhx '3099d2bbbfcb2538542dcd5fb078b6ef5f3d6fe2c745de65'
Gx=. dfhx '188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012'
Gy=. dfhx '07192b95ffc8da78631011ed6b24cdd573f977a11e794811'
c192=. (p;_3;b) conew 'CurveFp'
p192=. (c192;Gx;Gy;r) conew 'Point'
d=. 651056770906015076056810763456358567190100156695615665659x
Q=. mul__p192 d
if. (x0__Q'') ~: dfhx '62B12D60690CDCF330BABAB6E69763B471F994DD702D16A5' do.
smoutput 'p192 * d came out wrong.'
else.
smoutput 'p192 * d came out right.'
end.
k=. 6140507067065001063065065565667405560006161556565665656654x
R=. k * x0__p192''
if. (xy__R'') ~: dfhx&> '885052380FF147B734C330C43D39B2C4A89F29B0F749FEAD';'9CF9FA1CBEFEFB917747A3BB29C072B9289C2547884FD835' do.
smoutput 'k * p192 came out wrong.'
else.
smoutput 'k * p192 came out right.'
end.
u1=. 2563697409189434185194736134579731015366492496392189760599x
u2=. 6266643813348617967186477710235785849136406323338782220568x
temp=. mul__p192 u1
temp=. add_temp_ mul__Q u2
if. (xy_temp_'') ~: dfhx&> '885052380FF147B734C330C43D39B2C4A89F29B0F749FEAD';'9CF9FA1CBEFEFB917747A3BB29C072B9289C2547884FD835' do.
smoutput '(u1 * p192) + (u2 * Q) came out wrong.'
else.
smoutput '(u1 * p192) + (u2 * Q) came out right.'
end.
)
main''
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment