前回作成したコードではWeierstrass標準形とMontgomery curvesを同時に実行した.今回はMontgomery curvesのみで実行してみる.
\\m-n==1
add(P1,Pm,Pn,p)={
local(a,b,c,d,Xmn,Zmn);
if(Pm==0||Pm[2]==0,return(Pn));
if(Pn==0||Pn[2]==0,return(Pm));
a=Pm[1]+Pm[2];
b=Pm[1]-Pm[2];
c=Pn[1]+Pn[2];
d=Pn[1]-Pn[2];
Xmn=Mod(P1[2]*((b*c+a*d)^2),p);
Zmn=Mod(P1[1]*((b*c-a*d)^2),p);
return([Xmn,Zmn]);
}
dbl(A,P,p)={
local(tmp1,tmp2,tmp3,X2,Z2);
if(P==0||P[2]==0,return([0]));
tmp1=(P[1]+P[2])^2;
tmp2=(P[1]-P[2])^2;
tmp3=tmp1-tmp2;
X2=Mod(tmp1*tmp2,p);
Z2=Mod(tmp3*(tmp2+((tmp3*(A+2))/4)),p);
return([X2,Z2]);
}
recover(A,B,x1,y1,xn,xn1,p)={
local(up,down,res);
if(xn1==-1,
return(-y1);
);
up=(x1*xn+1)*(x1+xn+2*A)-2*A-((x1-xn)^2)*xn1;
down=2*B*y1;
if(down==0,
res=0;,
res=Mod(up/down,p);
);
return(res);
}
ladder(A,P,k,p)={
local(R0,R1,i,bin);
bin=binary(k);
R0=[0];
R1=P;
for(i=1,length(bin),
if(bin[i]==0,
R1=add(P,R1,R0,p);
R0=dbl(A,R0,p);,
R0=add(P,R1,R0,p);
R1=dbl(A,R1,p);
);
);
return([R1,R0]);
}
\\input and output is affine point P=(x,y)
scalar(A,B,P,k,p)={
local(P_M,pair,kP_M,k1P_M,x_k,x_k1,y_k);
P_M=[P[1],1];
pair=ladder(A,P_M,k,p);
kP_M=pair[2];k1P_M=pair[1];
if(kP_M!=[0]&&kP_M[2]==0,kP_M=[0]);
if(k1P_M!=[0]&&k1P_M[2]==0,k1P_M=[0]);
if(kP_M==[0],
return([0]);
);
if(kP_M!=[0],
x_k=Mod(kP_M[1]/kP_M[2],p);
if(k1P_M==[0]||k1P_M[2]==0,
x_k1=-1;,
x_k1=Mod(k1P_M[1]/k1P_M[2],p);
);
y_k=recover(A,B,P_M[1],P[2],x_k,x_k1,p);
);
return([x_k,y_k]);
}
mdbl(A,B,P,p)={
local(x,y);
x=Mod(((P[1]^2-1)^2)/(4*B*(P[2]^2)),p);
y=Mod(((2*P[1]+P[1]+A)*(3*(P[1]^2)+2*A*P[1]+1))/(2*B*P[2])-(B*(3*(((P[1]^2)+2*A*P[1]+1)^3)))/((2*B*P[2])^3)-P[2],p);
return([x,y]);
}
madd(A,B,P1,P2,p)={
local(x,y);
if(P1==[0],return(P2));
if(P2==[0],return(P1));
if(P1[1]==P2[1],
if(P1[2]==-P2[2],
return([0]);,
return(mdbl(A,B,P1,p));
);
);
x=Mod((B*((P2[2]-P1[2])^2))/((P2[1]-P1[1])^2)-A-P1[1]-P2[1],p);
y=Mod(((2*P1[1]+P2[1]+A)*(P2[2]-P1[2]))/(P2[1]-P1[1])-(B*((P2[2]-P1[2])^3))/((P2[1]-P1[1])^3)-P1[2],p);
return([x,y]);
}
{
\\準備
A=84;B=1;p=30011;
P=[Mod(7768,p),Mod(9454,p)];
l=1249;
print("pripare");
print("\tbase point P=",P);
print("\torder l=",l,"\n");
\\鍵生成
d_B=random(l-2)+2;
P_B=scalar(A,B,P,d_B,p);
print("key generation");
print("\tsecret key d_B =",d_B);
print("\tpublic key P_B =",P_B,"\n");
\\署名生成
until(u!=0&&v!=0,
r=random(l-1)+1;
U=scalar(A,B,P,r,p);
m=random(p);
u=lift(lift(U[1])%l);
v=((m+u*d_B)/r)%l;
);
print("signature generation");
print("\trandom value r=",r);
print("\tU=",U);
print("\tm=",m);
print("\tsignature (u,v)=(",u,",",v,")","\n");
\\署名検証
d=(1/v)%l;
V=madd(A,B,scalar(A,B,P,d*m,p),scalar(A,B,P_B,d*u,p),p);
print("signature verification");
print("\td=",d);
print("\tV=",V,"\n");
\\結果表示
print("result");
print("\t(u,Vx)=(",u,",",lift(V[1])%l,")");
if(u==(lift(V[1])%l),
print("\tOK");,
print("\tNG");
);
}
(18:47) gp > \r m_ecdsa.gp
pripare
base point P=[Mod(7768, 30011), Mod(9454, 30011)]
order l=1249
key generation
secret key d_B =1047
public key P_B =[Mod(24356, 30011), Mod(3467, 30011)]
signature generation
random value r=40
U=[Mod(28450, 30011), Mod(25680, 30011)]
m=28429
signature (u,v)=(972,642)
signature verification
d=1142
V=[Mod(28450, 30011), Mod(25680, 30011)]
result
(u,Vx)=(972,972)
OK