| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| */ |
| |
| package XXX |
| //import "fmt" |
| |
| const WEIERSTRASS int=0 |
| const EDWARDS int=1 |
| const MONTGOMERY int=2 |
| const NOT int=0 |
| const BN int=1 |
| const BLS int=2 |
| const D_TYPE int=0 |
| const M_TYPE int=1 |
| const POSITIVEX int=0 |
| const NEGATIVEX int=1 |
| |
| const CURVETYPE int=@CT@ |
| const CURVE_PAIRING_TYPE int=@PF@ |
| const SEXTIC_TWIST int=@ST@ |
| const SIGN_OF_X int=@SX@ |
| |
| const HASH_TYPE int=@HT@ |
| const AESKEY int=@AK@ |
| |
| /* Elliptic Curve Point Structure */ |
| |
| type ECP struct { |
| x *FP |
| y *FP |
| z *FP |
| // INF bool |
| } |
| |
| /* Constructors */ |
| func NewECP() *ECP { |
| E:=new(ECP) |
| E.x=NewFPint(0) |
| E.y=NewFPint(1) |
| if CURVETYPE==EDWARDS { |
| E.z=NewFPint(1) |
| } else { |
| E.z=NewFPint(0) |
| } |
| // E.INF=true |
| return E |
| } |
| |
| /* set (x,y) from two BIGs */ |
| func NewECPbigs(ix *BIG,iy *BIG) *ECP { |
| E:=new(ECP) |
| E.x=NewFPbig(ix) |
| E.y=NewFPbig(iy) |
| E.z=NewFPint(1) |
| E.x.norm() |
| rhs:=RHS(E.x) |
| |
| if CURVETYPE==MONTGOMERY { |
| if rhs.jacobi()!=1 { |
| E.inf() |
| } |
| } else { |
| y2:=NewFPcopy(E.y) |
| y2.sqr() |
| if !y2.Equals(rhs) { |
| E.inf() |
| } |
| } |
| return E |
| } |
| |
| /* set (x,y) from BIG and a bit */ |
| func NewECPbigint(ix *BIG,s int) *ECP { |
| E:=new(ECP) |
| E.x=NewFPbig(ix) |
| E.y=NewFPint(0) |
| E.x.norm() |
| rhs:=RHS(E.x) |
| E.z=NewFPint(1) |
| if rhs.jacobi()==1 { |
| ny:=rhs.sqrt() |
| if ny.redc().parity()!=s {ny.neg()} |
| E.y.copy(ny) |
| //E.INF=false |
| } else {E.inf()} |
| return E; |
| } |
| |
| /* set from x - calculate y from curve equation */ |
| func NewECPbig(ix *BIG) *ECP { |
| E:=new(ECP) |
| E.x=NewFPbig(ix) |
| E.y=NewFPint(0) |
| E.x.norm() |
| rhs:=RHS(E.x) |
| E.z=NewFPint(1) |
| if rhs.jacobi()==1 { |
| if CURVETYPE!=MONTGOMERY {E.y.copy(rhs.sqrt())} |
| //E.INF=false |
| } else {E.inf()} |
| return E |
| } |
| |
| /* test for O point-at-infinity */ |
| func (E *ECP) Is_infinity() bool { |
| // if E.INF {return true} |
| E.x.reduce(); E.z.reduce() |
| if CURVETYPE==EDWARDS { |
| E.y.reduce(); |
| return (E.x.iszilch() && E.y.Equals(E.z)) |
| } |
| if CURVETYPE==WEIERSTRASS { |
| E.y.reduce(); |
| return (E.x.iszilch() && E.z.iszilch()) |
| } |
| if CURVETYPE==MONTGOMERY { |
| return E.z.iszilch() |
| } |
| return true |
| } |
| |
| /* Conditional swap of P and Q dependant on d */ |
| func (E *ECP) cswap(Q *ECP,d int) { |
| E.x.cswap(Q.x,d) |
| if CURVETYPE!=MONTGOMERY {E.y.cswap(Q.y,d)} |
| E.z.cswap(Q.z,d) |
| /* |
| bd:=true |
| if d==0 {bd=false} |
| bd=bd&&(E.INF!=Q.INF) |
| E.INF=(bd!=E.INF) |
| Q.INF=(bd!=Q.INF) |
| */ |
| } |
| |
| /* Conditional move of Q to P dependant on d */ |
| func (E *ECP) cmove(Q *ECP,d int) { |
| E.x.cmove(Q.x,d) |
| if CURVETYPE!=MONTGOMERY {E.y.cmove(Q.y,d)} |
| E.z.cmove(Q.z,d); |
| /* |
| bd:=true |
| if d==0 {bd=false} |
| E.INF=(E.INF!=((E.INF!=Q.INF)&&bd)) |
| */ |
| } |
| |
| /* return 1 if b==c, no branching */ |
| func teq(b int32,c int32) int { |
| x:=b^c |
| x-=1 // if x=0, x now -1 |
| return int((x>>31)&1) |
| } |
| |
| /* this=P */ |
| func (E *ECP) Copy(P *ECP) { |
| E.x.copy(P.x); |
| if CURVETYPE!=MONTGOMERY {E.y.copy(P.y)} |
| E.z.copy(P.z); |
| // E.INF=P.INF; |
| } |
| |
| /* this=-this */ |
| func (E *ECP) neg() { |
| // if E.Is_infinity() {return} |
| if CURVETYPE==WEIERSTRASS { |
| E.y.neg(); E.y.norm() |
| } |
| if CURVETYPE==EDWARDS { |
| E.x.neg(); E.x.norm() |
| } |
| return; |
| } |
| |
| /* Constant time select from pre-computed table */ |
| func (E *ECP) selector(W []*ECP,b int32) { |
| MP:=NewECP() |
| m:=b>>31; |
| babs:=(b^m)-m; |
| |
| babs=(babs-1)/2 |
| |
| E.cmove(W[0],teq(babs,0)) // conditional move |
| E.cmove(W[1],teq(babs,1)) |
| E.cmove(W[2],teq(babs,2)) |
| E.cmove(W[3],teq(babs,3)) |
| E.cmove(W[4],teq(babs,4)) |
| E.cmove(W[5],teq(babs,5)) |
| E.cmove(W[6],teq(babs,6)) |
| E.cmove(W[7],teq(babs,7)) |
| |
| MP.Copy(E); |
| MP.neg() |
| E.cmove(MP,int(m&1)); |
| } |
| |
| /* set this=O */ |
| func (E *ECP) inf() { |
| // E.INF=true; |
| E.x.zero() |
| if CURVETYPE!=MONTGOMERY {E.y.one()} |
| if CURVETYPE!=EDWARDS { |
| E.z.zero() |
| } else {E.z.one()} |
| } |
| |
| /* Test P == Q */ |
| func( E *ECP) Equals(Q *ECP) bool { |
| // if E.Is_infinity() && Q.Is_infinity() {return true} |
| // if E.Is_infinity() || Q.Is_infinity() {return false} |
| |
| a:=NewFPint(0) |
| b:=NewFPint(0) |
| a.copy(E.x); a.mul(Q.z); a.reduce() |
| b.copy(Q.x); b.mul(E.z); b.reduce() |
| if !a.Equals(b) {return false} |
| if CURVETYPE!=MONTGOMERY { |
| a.copy(E.y); a.mul(Q.z); a.reduce() |
| b.copy(Q.y); b.mul(E.z); b.reduce() |
| if !a.Equals(b) {return false} |
| } |
| |
| return true |
| } |
| |
| /* Calculate RHS of curve equation */ |
| func RHS(x *FP) *FP { |
| //x.norm() |
| r:=NewFPcopy(x) |
| r.sqr(); |
| |
| if CURVETYPE==WEIERSTRASS { // x^3+Ax+B |
| b:=NewFPbig(NewBIGints(CURVE_B)) |
| r.mul(x); |
| if CURVE_A==-3 { |
| cx:=NewFPcopy(x) |
| cx.imul(3) |
| cx.neg(); cx.norm() |
| r.add(cx) |
| } |
| r.add(b) |
| } |
| if CURVETYPE==EDWARDS { // (Ax^2-1)/(Bx^2-1) |
| b:=NewFPbig(NewBIGints(CURVE_B)) |
| |
| one:=NewFPint(1) |
| b.mul(r) |
| b.sub(one) |
| b.norm() |
| if CURVE_A==-1 {r.neg()} |
| r.sub(one); r.norm() |
| b.inverse() |
| r.mul(b) |
| } |
| if CURVETYPE==MONTGOMERY { // x^3+Ax^2+x |
| x3:=NewFPint(0) |
| x3.copy(r) |
| x3.mul(x) |
| r.imul(CURVE_A) |
| r.add(x3) |
| r.add(x) |
| } |
| r.reduce() |
| return r |
| } |
| |
| /* set to affine - from (x,y,z) to (x,y) */ |
| func (E *ECP) Affine() { |
| if E.Is_infinity() {return} |
| one:=NewFPint(1) |
| if E.z.Equals(one) {return} |
| E.z.inverse() |
| E.x.mul(E.z); E.x.reduce() |
| |
| if CURVETYPE!=MONTGOMERY { |
| E.y.mul(E.z); E.y.reduce() |
| } |
| E.z.copy(one) |
| } |
| |
| /* extract x as a BIG */ |
| func (E *ECP) GetX() *BIG { |
| W:=NewECP(); W.Copy(E) |
| W.Affine() |
| return W.x.redc() |
| } |
| /* extract y as a BIG */ |
| func (E *ECP) GetY() *BIG { |
| W:=NewECP(); W.Copy(E) |
| W.Affine() |
| return W.y.redc() |
| } |
| |
| /* get sign of Y */ |
| func (E *ECP) GetS() int { |
| //E.Affine() |
| y:=E.GetY() |
| return y.parity() |
| } |
| /* extract x as an FP */ |
| func (E *ECP) getx() *FP { |
| return E.x; |
| } |
| /* extract y as an FP */ |
| func (E *ECP) gety() *FP { |
| return E.y |
| } |
| /* extract z as an FP */ |
| func (E *ECP) getz() *FP { |
| return E.z |
| } |
| |
| /* convert to byte array */ |
| func (E *ECP) ToBytes(b []byte,compress bool) { |
| var t [int(MODBYTES)]byte |
| MB:=int(MODBYTES) |
| W:=NewECP(); W.Copy(E); |
| W.Affine() |
| W.x.redc().ToBytes(t[:]) |
| for i:=0;i<MB;i++ {b[i+1]=t[i]} |
| |
| if CURVETYPE==MONTGOMERY { |
| b[0]=0x06 |
| return; |
| } |
| |
| if compress { |
| b[0]=0x02 |
| if W.y.redc().parity()==1 {b[0]=0x03} |
| return; |
| } |
| |
| b[0]=0x04 |
| |
| W.y.redc().ToBytes(t[:]) |
| for i:=0;i<MB;i++ {b[i+MB+1]=t[i]} |
| } |
| |
| /* convert from byte array to point */ |
| func ECP_fromBytes(b []byte) *ECP { |
| var t [int(MODBYTES)]byte |
| MB:=int(MODBYTES) |
| p:=NewBIGints(Modulus) |
| |
| for i:=0;i<MB;i++ {t[i]=b[i+1]} |
| px:=FromBytes(t[:]) |
| if Comp(px,p)>=0 {return NewECP()} |
| |
| if CURVETYPE==MONTGOMERY { |
| return NewECPbig(px) |
| } |
| |
| if b[0]==0x04 { |
| for i:=0;i<MB;i++ {t[i]=b[i+MB+1]} |
| py:=FromBytes(t[:]) |
| if Comp(py,p)>=0 {return NewECP()} |
| return NewECPbigs(px,py) |
| } |
| |
| if b[0]==0x02 || b[0]==0x03 { |
| return NewECPbigint(px,int(b[0]&1)) |
| } |
| |
| return NewECP() |
| } |
| |
| /* convert to hex string */ |
| func (E *ECP) ToString() string { |
| W:=NewECP(); W.Copy(E); |
| W.Affine() |
| if W.Is_infinity() {return "infinity"} |
| if CURVETYPE==MONTGOMERY { |
| return "("+W.x.redc().ToString()+")" |
| } else {return "("+W.x.redc().ToString()+","+W.y.redc().ToString()+")"} |
| } |
| |
| /* this*=2 */ |
| func (E *ECP) dbl() { |
| |
| // if E.INF {return} |
| if CURVETYPE==WEIERSTRASS { |
| if CURVE_A==0 { |
| t0:=NewFPcopy(E.y) /*** Change ***/ // Edits made |
| t0.sqr() |
| t1:=NewFPcopy(E.y) |
| t1.mul(E.z) |
| t2:=NewFPcopy(E.z) |
| t2.sqr() |
| |
| E.z.copy(t0) |
| E.z.add(t0); E.z.norm(); |
| E.z.add(E.z); E.z.add(E.z); E.z.norm() |
| t2.imul(3*CURVE_B_I) |
| |
| x3:=NewFPcopy(t2) |
| x3.mul(E.z) |
| |
| y3:=NewFPcopy(t0) |
| y3.add(t2); y3.norm() |
| E.z.mul(t1) |
| t1.copy(t2); t1.add(t2); t2.add(t1) |
| t0.sub(t2); t0.norm(); y3.mul(t0); y3.add(x3) |
| t1.copy(E.x); t1.mul(E.y) |
| E.x.copy(t0); E.x.norm(); E.x.mul(t1); E.x.add(E.x) |
| E.x.norm(); |
| E.y.copy(y3); E.y.norm(); |
| } else { |
| t0:=NewFPcopy(E.x) |
| t1:=NewFPcopy(E.y) |
| t2:=NewFPcopy(E.z) |
| t3:=NewFPcopy(E.x) |
| z3:=NewFPcopy(E.z) |
| y3:=NewFPint(0) |
| x3:=NewFPint(0) |
| b:=NewFPint(0) |
| |
| if CURVE_B_I==0 {b.copy(NewFPbig(NewBIGints(CURVE_B)))} |
| |
| t0.sqr() //1 x^2 |
| t1.sqr() //2 y^2 |
| t2.sqr() //3 |
| |
| t3.mul(E.y) //4 |
| t3.add(t3); t3.norm() //5 |
| z3.mul(E.x); //6 |
| z3.add(z3); z3.norm()//7 |
| y3.copy(t2) |
| |
| if CURVE_B_I==0 { |
| y3.mul(b) |
| } else { |
| y3.imul(CURVE_B_I) |
| } |
| |
| y3.sub(z3) //y3.norm(); //9 *** |
| x3.copy(y3); x3.add(y3); x3.norm() //10 |
| |
| y3.add(x3) //y3.norm();//11 |
| x3.copy(t1); x3.sub(y3); x3.norm() //12 |
| y3.add(t1); y3.norm() //13 |
| y3.mul(x3) //14 |
| x3.mul(t3) //15 |
| t3.copy(t2); t3.add(t2) //t3.norm(); //16 |
| t2.add(t3) //t2.norm(); //17 |
| |
| if CURVE_B_I==0 { |
| z3.mul(b) |
| } else { |
| z3.imul(CURVE_B_I) |
| } |
| |
| z3.sub(t2) //z3.norm();//19 |
| z3.sub(t0); z3.norm()//20 *** |
| t3.copy(z3); t3.add(z3) //t3.norm();//21 |
| |
| z3.add(t3); z3.norm() //22 |
| t3.copy(t0); t3.add(t0) //t3.norm(); //23 |
| t0.add(t3) //t0.norm();//24 |
| t0.sub(t2); t0.norm() //25 |
| |
| t0.mul(z3) //26 |
| y3.add(t0) //y3.norm();//27 |
| t0.copy(E.y); t0.mul(E.z)//28 |
| t0.add(t0); t0.norm() //29 |
| z3.mul(t0)//30 |
| x3.sub(z3) //x3.norm();//31 |
| t0.add(t0); t0.norm() //32 |
| t1.add(t1); t1.norm() //33 |
| z3.copy(t0); z3.mul(t1) //34 |
| |
| E.x.copy(x3); E.x.norm() |
| E.y.copy(y3); E.y.norm() |
| E.z.copy(z3); E.z.norm() |
| } |
| } |
| |
| if CURVETYPE==EDWARDS { |
| C:=NewFPcopy(E.x) |
| D:=NewFPcopy(E.y) |
| H:=NewFPcopy(E.z) |
| J:=NewFPint(0) |
| |
| E.x.mul(E.y); E.x.add(E.x); E.x.norm() |
| C.sqr() |
| D.sqr() |
| if CURVE_A==-1 {C.neg()} |
| E.y.copy(C); E.y.add(D); E.y.norm() |
| |
| H.sqr(); H.add(H) |
| E.z.copy(E.y) |
| J.copy(E.y); J.sub(H); J.norm() |
| E.x.mul(J) |
| C.sub(D); C.norm() |
| E.y.mul(C) |
| E.z.mul(J) |
| |
| |
| } |
| if CURVETYPE==MONTGOMERY { |
| A:=NewFPcopy(E.x) |
| B:=NewFPcopy(E.x) |
| AA:=NewFPint(0) |
| BB:=NewFPint(0) |
| C:=NewFPint(0) |
| |
| // if E.INF {return} |
| |
| A.add(E.z); A.norm() |
| AA.copy(A); AA.sqr() |
| B.sub(E.z); B.norm() |
| BB.copy(B); BB.sqr() |
| C.copy(AA); C.sub(BB) |
| C.norm() |
| |
| E.x.copy(AA); E.x.mul(BB) |
| |
| A.copy(C); A.imul((CURVE_A+2)/4) |
| |
| BB.add(A); BB.norm() |
| E.z.copy(BB); E.z.mul(C) |
| } |
| return; |
| } |
| |
| /* this+=Q */ |
| func (E *ECP) Add(Q *ECP) { |
| /* |
| if E.INF { |
| E.Copy(Q) |
| return |
| } |
| if Q.INF {return} |
| */ |
| if CURVETYPE==WEIERSTRASS { |
| if CURVE_A==0 { |
| b:=3*CURVE_B_I |
| t0:=NewFPcopy(E.x) |
| t0.mul(Q.x) |
| t1:=NewFPcopy(E.y) |
| t1.mul(Q.y) |
| t2:=NewFPcopy(E.z) |
| t2.mul(Q.z) |
| t3:=NewFPcopy(E.x) |
| t3.add(E.y); t3.norm() |
| t4:=NewFPcopy(Q.x) |
| t4.add(Q.y); t4.norm() |
| t3.mul(t4) |
| t4.copy(t0); t4.add(t1) |
| |
| t3.sub(t4); t3.norm() |
| t4.copy(E.y) |
| t4.add(E.z); t4.norm() |
| x3:=NewFPcopy(Q.y) |
| x3.add(Q.z); x3.norm() |
| |
| t4.mul(x3) |
| x3.copy(t1) |
| x3.add(t2) |
| |
| t4.sub(x3); t4.norm() |
| x3.copy(E.x); x3.add(E.z); x3.norm() |
| y3:=NewFPcopy(Q.x) |
| y3.add(Q.z); y3.norm() |
| x3.mul(y3) |
| y3.copy(t0) |
| y3.add(t2) |
| y3.rsub(x3); y3.norm() |
| x3.copy(t0); x3.add(t0) |
| t0.add(x3); t0.norm() |
| t2.imul(b) |
| |
| z3:=NewFPcopy(t1); z3.add(t2); z3.norm() |
| t1.sub(t2); t1.norm() |
| y3.imul(b) |
| |
| x3.copy(y3); x3.mul(t4); t2.copy(t3); t2.mul(t1); x3.rsub(t2) |
| y3.mul(t0); t1.mul(z3); y3.add(t1) |
| t0.mul(t3); z3.mul(t4); z3.add(t0) |
| |
| E.x.copy(x3); E.x.norm() |
| E.y.copy(y3); E.y.norm() |
| E.z.copy(z3); E.z.norm() |
| } else { |
| |
| t0:=NewFPcopy(E.x) |
| t1:=NewFPcopy(E.y) |
| t2:=NewFPcopy(E.z) |
| t3:=NewFPcopy(E.x) |
| t4:=NewFPcopy(Q.x) |
| z3:=NewFPint(0) |
| y3:=NewFPcopy(Q.x) |
| x3:=NewFPcopy(Q.y) |
| b:=NewFPint(0) |
| |
| if CURVE_B_I==0 {b.copy(NewFPbig(NewBIGints(CURVE_B)))} |
| |
| t0.mul(Q.x) //1 |
| t1.mul(Q.y) //2 |
| t2.mul(Q.z) //3 |
| |
| t3.add(E.y); t3.norm() //4 |
| t4.add(Q.y); t4.norm() //5 |
| t3.mul(t4) //6 |
| t4.copy(t0); t4.add(t1) //t4.norm(); //7 |
| t3.sub(t4); t3.norm() //8 |
| t4.copy(E.y); t4.add(E.z); t4.norm() //9 |
| x3.add(Q.z); x3.norm() //10 |
| t4.mul(x3) //11 |
| x3.copy(t1); x3.add(t2) //x3.norm();//12 |
| |
| t4.sub(x3); t4.norm() //13 |
| x3.copy(E.x); x3.add(E.z); x3.norm() //14 |
| y3.add(Q.z); y3.norm() //15 |
| |
| x3.mul(y3) //16 |
| y3.copy(t0); y3.add(t2) //y3.norm();//17 |
| |
| y3.rsub(x3); y3.norm() //18 |
| z3.copy(t2) |
| |
| if CURVE_B_I==0 { |
| z3.mul(b) |
| } else { |
| z3.imul(CURVE_B_I) |
| } |
| |
| x3.copy(y3); x3.sub(z3); x3.norm() //20 |
| z3.copy(x3); z3.add(x3) //z3.norm(); //21 |
| |
| x3.add(z3) //x3.norm(); //22 |
| z3.copy(t1); z3.sub(x3); z3.norm() //23 |
| x3.add(t1); x3.norm() //24 |
| |
| if CURVE_B_I==0 { |
| y3.mul(b) |
| } else { |
| y3.imul(CURVE_B_I) |
| } |
| |
| t1.copy(t2); t1.add(t2); //t1.norm();//26 |
| t2.add(t1) //t2.norm();//27 |
| |
| y3.sub(t2) //y3.norm(); //28 |
| |
| y3.sub(t0); y3.norm() //29 |
| t1.copy(y3); t1.add(y3) //t1.norm();//30 |
| y3.add(t1); y3.norm() //31 |
| |
| t1.copy(t0); t1.add(t0) //t1.norm(); //32 |
| t0.add(t1) //t0.norm();//33 |
| t0.sub(t2); t0.norm() //34 |
| t1.copy(t4); t1.mul(y3) //35 |
| t2.copy(t0); t2.mul(y3) //36 |
| y3.copy(x3); y3.mul(z3) //37 |
| y3.add(t2) //y3.norm();//38 |
| x3.mul(t3) //39 |
| x3.sub(t1) //40 |
| z3.mul(t4) //41 |
| t1.copy(t3); t1.mul(t0) //42 |
| z3.add(t1) |
| E.x.copy(x3); E.x.norm() |
| E.y.copy(y3); E.y.norm() |
| E.z.copy(z3); E.z.norm() |
| |
| } |
| } |
| if CURVETYPE==EDWARDS { |
| b:=NewFPbig(NewBIGints(CURVE_B)) |
| A:=NewFPcopy(E.z) |
| B:=NewFPint(0) |
| C:=NewFPcopy(E.x) |
| D:=NewFPcopy(E.y) |
| EE:=NewFPint(0) |
| F:=NewFPint(0) |
| G:=NewFPint(0) |
| |
| A.mul(Q.z); |
| B.copy(A); B.sqr() |
| C.mul(Q.x) |
| D.mul(Q.y) |
| |
| EE.copy(C); EE.mul(D); EE.mul(b) |
| F.copy(B); F.sub(EE) |
| G.copy(B); G.add(EE) |
| |
| if CURVE_A==1 { |
| EE.copy(D); EE.sub(C) |
| } |
| C.add(D) |
| |
| B.copy(E.x); B.add(E.y) |
| D.copy(Q.x); D.add(Q.y) |
| B.norm(); D.norm() |
| B.mul(D) |
| B.sub(C) |
| B.norm(); F.norm() |
| B.mul(F) |
| E.x.copy(A); E.x.mul(B) |
| G.norm() |
| if CURVE_A==1 { |
| EE.norm(); C.copy(EE); C.mul(G) |
| } |
| if CURVE_A==-1 { |
| C.norm(); C.mul(G) |
| } |
| E.y.copy(A); E.y.mul(C) |
| E.z.copy(F); E.z.mul(G) |
| } |
| return |
| } |
| |
| /* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */ |
| func (E *ECP) dadd(Q *ECP,W *ECP) { |
| A:=NewFPcopy(E.x) |
| B:=NewFPcopy(E.x) |
| C:=NewFPcopy(Q.x) |
| D:=NewFPcopy(Q.x) |
| DA:=NewFPint(0) |
| CB:=NewFPint(0) |
| |
| A.add(E.z) |
| B.sub(E.z) |
| |
| C.add(Q.z) |
| D.sub(Q.z) |
| A.norm(); D.norm() |
| |
| DA.copy(D); DA.mul(A) |
| C.norm(); B.norm() |
| |
| CB.copy(C); CB.mul(B) |
| |
| A.copy(DA); A.add(CB); A.norm(); A.sqr() |
| B.copy(DA); B.sub(CB); B.norm(); B.sqr() |
| |
| E.x.copy(A) |
| E.z.copy(W.x); E.z.mul(B) |
| |
| // if E.z.iszilch() { |
| // E.inf() |
| // } else {E.INF=false;} |
| |
| } |
| |
| /* this-=Q */ |
| func (E *ECP) Sub(Q *ECP) { |
| NQ:=NewECP(); NQ.Copy(Q); |
| NQ.neg() |
| E.Add(NQ) |
| } |
| |
| /* constant time multiply by small integer of length bts - use ladder */ |
| func (E *ECP) pinmul(e int32,bts int32) *ECP { |
| if CURVETYPE==MONTGOMERY { |
| return E.mul(NewBIGint(int(e))) |
| } else { |
| P:=NewECP() |
| R0:=NewECP() |
| R1:=NewECP(); R1.Copy(E) |
| |
| for i:=bts-1;i>=0;i-- { |
| b:=int((e>>uint32(i))&1) |
| P.Copy(R1) |
| P.Add(R0) |
| R0.cswap(R1,b) |
| R1.Copy(P) |
| R0.dbl() |
| R0.cswap(R1,b) |
| } |
| P.Copy(R0) |
| P.Affine() |
| return P |
| } |
| } |
| |
| /* return e.this */ |
| |
| func (E *ECP) mul(e *BIG) *ECP { |
| if (e.iszilch() || E.Is_infinity()) {return NewECP()} |
| P:=NewECP() |
| if CURVETYPE==MONTGOMERY { |
| /* use Ladder */ |
| D:=NewECP(); |
| R0:=NewECP(); R0.Copy(E) |
| R1:=NewECP(); R1.Copy(E) |
| R1.dbl() |
| D.Copy(E); D.Affine() |
| nb:=e.nbits() |
| for i:=nb-2;i>=0;i-- { |
| b:=int(e.bit(i)) |
| P.Copy(R1) |
| P.dadd(R0,D) |
| R0.cswap(R1,b) |
| R1.Copy(P) |
| R0.dbl() |
| R0.cswap(R1,b) |
| } |
| P.Copy(R0) |
| } else { |
| // fixed size windows |
| mt:=NewBIG() |
| t:=NewBIG() |
| Q:=NewECP() |
| C:=NewECP() |
| |
| var W []*ECP |
| var w [1+(NLEN*int(BASEBITS)+3)/4]int8 |
| |
| //E.Affine(); |
| |
| Q.Copy(E); |
| Q.dbl(); |
| |
| W=append(W,NewECP()); |
| W[0].Copy(E); |
| |
| for i:=1;i<8;i++ { |
| W=append(W,NewECP()) |
| W[i].Copy(W[i-1]) |
| W[i].Add(Q) |
| } |
| |
| // make exponent odd - add 2P if even, P if odd |
| t.copy(e) |
| s:=int(t.parity()) |
| t.inc(1); t.norm(); ns:=int(t.parity()); mt.copy(t); mt.inc(1); mt.norm() |
| t.cmove(mt,s) |
| Q.cmove(E,ns) |
| C.Copy(Q) |
| |
| nb:=1+(t.nbits()+3)/4 |
| |
| // convert exponent to signed 4-bit window |
| for i:=0;i<nb;i++ { |
| w[i]=int8(t.lastbits(5)-16) |
| t.dec(int(w[i])); t.norm() |
| t.fshr(4) |
| } |
| w[nb]=int8(t.lastbits(5)) |
| |
| P.Copy(W[(int(w[nb])-1)/2]) |
| for i:=nb-1;i>=0;i-- { |
| Q.selector(W,int32(w[i])) |
| P.dbl() |
| P.dbl() |
| P.dbl() |
| P.dbl() |
| P.Add(Q) |
| } |
| P.Sub(C) /* apply correction */ |
| } |
| P.Affine() |
| return P |
| } |
| |
| /* Public version */ |
| func (E *ECP) Mul(e *BIG) *ECP { |
| return E.mul(e) |
| } |
| |
| /* Return e.this+f.Q */ |
| |
| func (E *ECP) Mul2(e *BIG,Q *ECP,f *BIG) *ECP { |
| te:=NewBIG() |
| tf:=NewBIG() |
| mt:=NewBIG() |
| S:=NewECP() |
| T:=NewECP() |
| C:=NewECP() |
| var W [] *ECP |
| //ECP[] W=new ECP[8]; |
| var w [1+(NLEN*int(BASEBITS)+1)/2]int8 |
| |
| //E.Affine() |
| //Q.Affine() |
| |
| te.copy(e) |
| tf.copy(f) |
| |
| // precompute table |
| for i:=0;i<8;i++ { |
| W=append(W,NewECP()) |
| } |
| W[1].Copy(E); W[1].Sub(Q) |
| W[2].Copy(E); W[2].Add(Q); |
| S.Copy(Q); S.dbl(); |
| W[0].Copy(W[1]); W[0].Sub(S); |
| W[3].Copy(W[2]); W[3].Add(S); |
| T.Copy(E); T.dbl(); |
| W[5].Copy(W[1]); W[5].Add(T); |
| W[6].Copy(W[2]); W[6].Add(T); |
| W[4].Copy(W[5]); W[4].Sub(S); |
| W[7].Copy(W[6]); W[7].Add(S); |
| |
| // if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction |
| |
| s:=int(te.parity()); |
| te.inc(1); te.norm(); ns:=int(te.parity()); mt.copy(te); mt.inc(1); mt.norm() |
| te.cmove(mt,s) |
| T.cmove(E,ns) |
| C.Copy(T) |
| |
| s=int(tf.parity()) |
| tf.inc(1); tf.norm(); ns=int(tf.parity()); mt.copy(tf); mt.inc(1); mt.norm() |
| tf.cmove(mt,s) |
| S.cmove(Q,ns) |
| C.Add(S) |
| |
| mt.copy(te); mt.add(tf); mt.norm() |
| nb:=1+(mt.nbits()+1)/2 |
| |
| // convert exponent to signed 2-bit window |
| for i:=0;i<nb;i++ { |
| a:=(te.lastbits(3)-4) |
| te.dec(int(a)); te.norm() |
| te.fshr(2) |
| b:=(tf.lastbits(3)-4) |
| tf.dec(int(b)); tf.norm() |
| tf.fshr(2) |
| w[i]=int8(4*a+b) |
| } |
| w[nb]=int8(4*te.lastbits(3)+tf.lastbits(3)) |
| S.Copy(W[(w[nb]-1)/2]) |
| |
| for i:=nb-1;i>=0;i-- { |
| T.selector(W,int32(w[i])); |
| S.dbl() |
| S.dbl() |
| S.Add(T) |
| } |
| S.Sub(C) /* apply correction */ |
| S.Affine() |
| return S |
| } |
| |
| func (E *ECP) cfp() { |
| cf:=CURVE_Cof_I; |
| if cf==1 {return} |
| if cf==4 { |
| E.dbl(); E.dbl() |
| //E.Affine(); |
| return; |
| } |
| if cf==8 { |
| E.dbl(); E.dbl(); E.dbl() |
| //E.Affine(); |
| return; |
| } |
| c:=NewBIGints(CURVE_Cof); |
| E.Copy(E.mul(c)); |
| } |
| |
| func ECP_mapit(h []byte) *ECP { |
| q:=NewBIGints(Modulus) |
| x:=FromBytes(h[:]) |
| x.Mod(q) |
| var P *ECP |
| |
| for true { |
| for true { |
| if CURVETYPE!=MONTGOMERY { |
| P=NewECPbigint(x,0) |
| } else { |
| P=NewECPbig(x) |
| } |
| x.inc(1); x.norm() |
| if !P.Is_infinity() {break} |
| } |
| P.cfp() |
| if !P.Is_infinity() {break} |
| } |
| |
| return P |
| } |
| |
| func ECP_generator() *ECP { |
| var G *ECP |
| |
| gx:=NewBIGints(CURVE_Gx) |
| if CURVETYPE!=MONTGOMERY { |
| gy:=NewBIGints(CURVE_Gy) |
| G=NewECPbigs(gx,gy) |
| } else { |
| G=NewECPbig(gx) |
| } |
| return G |
| } |
| |
| /* |
| func main() { |
| Gx:=NewBIGints(CURVE_Gx); |
| var Gy *BIG |
| var P *ECP |
| |
| if CURVETYPE!=MONTGOMERY {Gy=NewBIGints(CURVE_Gy)} |
| r:=NewBIGints(CURVE_Order) |
| |
| //r.dec(7); |
| |
| fmt.Printf("Gx= "+Gx.ToString()) |
| fmt.Printf("\n") |
| |
| if CURVETYPE!=MONTGOMERY { |
| fmt.Printf("Gy= "+Gy.ToString()) |
| fmt.Printf("\n") |
| } |
| |
| if CURVETYPE!=MONTGOMERY { |
| P=NewECPbigs(Gx,Gy) |
| } else {P=NewECPbig(Gx)} |
| |
| fmt.Printf("P= "+P.ToString()); |
| fmt.Printf("\n") |
| |
| R:=P.mul(r); |
| //for (int i=0;i<10000;i++) |
| // R=P.mul(r); |
| |
| fmt.Printf("R= "+R.ToString()) |
| fmt.Printf("\n") |
| } |
| */ |