| /* |
| 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. |
| */ |
| |
| /* MiotCL Weierstrass elliptic curve functions over FP2 */ |
| |
| package XXX |
| |
| //import "fmt" |
| |
| type ECP2 struct { |
| x *FP2 |
| y *FP2 |
| z *FP2 |
| // INF bool |
| } |
| |
| func NewECP2() *ECP2 { |
| E:=new(ECP2) |
| E.x=NewFP2int(0) |
| E.y=NewFP2int(1) |
| E.z=NewFP2int(0) |
| // E.INF=true |
| return E |
| } |
| |
| /* Test this=O? */ |
| func (E *ECP2) Is_infinity() bool { |
| // if E.INF {return true} |
| E.x.reduce(); E.y.reduce(); E.z.reduce() |
| return E.x.iszilch() && E.z.iszilch() |
| } |
| /* copy this=P */ |
| func (E *ECP2) Copy(P *ECP2) { |
| E.x.copy(P.x) |
| E.y.copy(P.y) |
| E.z.copy(P.z) |
| // E.INF=P.INF |
| } |
| /* set this=O */ |
| func (E *ECP2) inf() { |
| // E.INF=true |
| E.x.zero() |
| E.y.one() |
| E.z.zero() |
| } |
| |
| /* set this=-this */ |
| func (E *ECP2) neg() { |
| // if E.Is_infinity() {return} |
| E.y.norm(); E.y.neg(); E.y.norm() |
| } |
| |
| /* Conditional move of Q to P dependant on d */ |
| func (E *ECP2) cmove(Q *ECP2,d int) { |
| E.x.cmove(Q.x,d) |
| E.y.cmove(Q.y,d) |
| E.z.cmove(Q.z,d) |
| /* |
| var bd bool |
| if (d==0) { |
| bd=false |
| } else {bd=true} |
| E.INF=(E.INF!=(E.INF!=Q.INF)&&bd) |
| */ |
| } |
| |
| /* Constant time select from pre-computed table */ |
| func (E *ECP2) selector(W []*ECP2,b int32) { |
| MP:=NewECP2() |
| 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)) |
| } |
| |
| /* Test if P == Q */ |
| func (E *ECP2) Equals(Q *ECP2) bool { |
| // if E.Is_infinity() && Q.Is_infinity() {return true} |
| // if E.Is_infinity() || Q.Is_infinity() {return false} |
| |
| a:=NewFP2copy(E.x) |
| b:=NewFP2copy(Q.x) |
| a.mul(Q.z); b.mul(E.z) |
| |
| if !a.Equals(b) {return false} |
| a.copy(E.y); b.copy(Q.y) |
| a.mul(Q.z); b.mul(E.z); |
| if !a.Equals(b) {return false} |
| |
| return true |
| } |
| |
| /* set to Affine - (x,y,z) to (x,y) */ |
| func (E *ECP2) Affine() { |
| if E.Is_infinity() {return} |
| one:=NewFP2int(1) |
| if E.z.Equals(one) {E.x.reduce(); E.y.reduce(); return} |
| E.z.inverse() |
| |
| E.x.mul(E.z); E.x.reduce() |
| E.y.mul(E.z); E.y.reduce() |
| E.z.copy(one) |
| } |
| |
| /* extract affine x as FP2 */ |
| func (E *ECP2) GetX() *FP2 { |
| W:=NewECP2(); W.Copy(E) |
| W.Affine() |
| return W.x |
| } |
| /* extract affine y as FP2 */ |
| func (E *ECP2) GetY() *FP2 { |
| W:=NewECP2(); W.Copy(E) |
| W.Affine() |
| return W.y; |
| } |
| /* extract projective x */ |
| func (E *ECP2) getx() *FP2 { |
| return E.x |
| } |
| /* extract projective y */ |
| func (E *ECP2) gety() *FP2 { |
| return E.y |
| } |
| /* extract projective z */ |
| func (E *ECP2) getz() *FP2 { |
| return E.z |
| } |
| |
| /* convert to byte array */ |
| func (E *ECP2) ToBytes(b []byte) { |
| var t [int(MODBYTES)]byte |
| MB:=int(MODBYTES) |
| |
| W:=NewECP2(); W.Copy(E); |
| W.Affine() |
| |
| W.x.GetA().ToBytes(t[:]) |
| for i:=0;i<MB;i++ { b[i]=t[i]} |
| W.x.GetB().ToBytes(t[:]) |
| for i:=0;i<MB;i++ { b[i+MB]=t[i]} |
| |
| W.y.GetA().ToBytes(t[:]) |
| for i:=0;i<MB;i++ {b[i+2*MB]=t[i]} |
| W.y.GetB().ToBytes(t[:]) |
| for i:=0;i<MB;i++ {b[i+3*MB]=t[i]} |
| } |
| |
| /* convert from byte array to point */ |
| func ECP2_fromBytes(b []byte) *ECP2 { |
| var t [int(MODBYTES)]byte |
| MB:=int(MODBYTES) |
| |
| for i:=0;i<MB;i++ {t[i]=b[i]} |
| ra:=FromBytes(t[:]) |
| for i:=0;i<MB;i++ {t[i]=b[i+MB]} |
| rb:=FromBytes(t[:]) |
| rx:=NewFP2bigs(ra,rb) |
| |
| for i:=0;i<MB;i++ {t[i]=b[i+2*MB]} |
| ra=FromBytes(t[:]) |
| for i:=0;i<MB;i++ {t[i]=b[i+3*MB]} |
| rb=FromBytes(t[:]) |
| ry:=NewFP2bigs(ra,rb) |
| |
| return NewECP2fp2s(rx,ry) |
| } |
| |
| /* convert this to hex string */ |
| func (E *ECP2) ToString() string { |
| W:=NewECP2(); W.Copy(E); |
| W.Affine() |
| if W.Is_infinity() {return "infinity"} |
| return "("+W.x.toString()+","+W.y.toString()+")" |
| } |
| |
| /* Calculate RHS of twisted curve equation x^3+B/i */ |
| func RHS2(x *FP2) *FP2 { |
| //x.norm() |
| r:=NewFP2copy(x) |
| r.sqr() |
| b:=NewFP2big(NewBIGints(CURVE_B)) |
| |
| if SEXTIC_TWIST == D_TYPE { |
| b.div_ip() |
| } |
| if SEXTIC_TWIST == M_TYPE { |
| b.norm() |
| b.mul_ip() |
| b.norm() |
| } |
| r.mul(x) |
| r.add(b) |
| |
| r.reduce() |
| return r |
| } |
| |
| /* construct this from (x,y) - but set to O if not on curve */ |
| func NewECP2fp2s(ix *FP2,iy *FP2) *ECP2 { |
| E:=new(ECP2) |
| E.x=NewFP2copy(ix) |
| E.y=NewFP2copy(iy) |
| E.z=NewFP2int(1) |
| E.x.norm() |
| rhs:=RHS2(E.x) |
| y2:=NewFP2copy(E.y) |
| y2.sqr() |
| if !y2.Equals(rhs) { |
| E.inf() |
| } |
| return E |
| } |
| |
| /* construct this from x - but set to O if not on curve */ |
| func NewECP2fp2(ix *FP2) *ECP2 { |
| E:=new(ECP2) |
| E.x=NewFP2copy(ix) |
| E.y=NewFP2int(1) |
| E.z=NewFP2int(1) |
| E.x.norm() |
| rhs:=RHS2(E.x) |
| if rhs.sqrt() { |
| E.y.copy(rhs) |
| //E.INF=false; |
| } else {E.inf()} |
| return E |
| } |
| |
| /* this+=this */ |
| func (E *ECP2) dbl() int { |
| // if E.INF {return -1} |
| |
| iy:=NewFP2copy(E.y) |
| if SEXTIC_TWIST == D_TYPE { |
| iy.mul_ip(); iy.norm() |
| } |
| |
| t0:=NewFP2copy(E.y) //***** Change |
| t0.sqr(); |
| if SEXTIC_TWIST == D_TYPE { |
| t0.mul_ip() |
| } |
| t1:=NewFP2copy(iy) |
| t1.mul(E.z) |
| t2:=NewFP2copy(E.z) |
| t2.sqr() // z^2 |
| |
| E.z.copy(t0) // y^2 |
| E.z.add(t0); E.z.norm() // 2y^2 |
| E.z.add(E.z) |
| E.z.add(E.z) // 8y^2 |
| E.z.norm() |
| |
| t2.imul(3*CURVE_B_I) // 3bz^2 |
| if SEXTIC_TWIST == M_TYPE { |
| t2.mul_ip() |
| t2.norm() |
| } |
| x3:=NewFP2copy(t2) |
| x3.mul(E.z) |
| |
| y3:=NewFP2copy(t0) |
| |
| y3.add(t2); y3.norm() |
| E.z.mul(t1) |
| t1.copy(t2); t1.add(t2); t2.add(t1); t2.norm() |
| t0.sub(t2); t0.norm() //y^2-9bz^2 |
| y3.mul(t0); y3.add(x3) //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2 |
| t1.copy(E.x); t1.mul(iy) // |
| E.x.copy(t0); E.x.norm(); E.x.mul(t1); E.x.add(E.x) //(y^2-9bz^2)xy2 |
| |
| E.x.norm() |
| E.y.copy(y3); E.y.norm() |
| |
| return 1 |
| } |
| |
| /* this+=Q - return 0 for add, 1 for double, -1 for O */ |
| func (E *ECP2) Add(Q *ECP2) int { |
| /* if E.INF { |
| E.Copy(Q) |
| return -1 |
| } |
| if Q.INF {return -1} |
| */ |
| b:=3*CURVE_B_I |
| t0:=NewFP2copy(E.x) |
| t0.mul(Q.x) // x.Q.x |
| t1:=NewFP2copy(E.y) |
| t1.mul(Q.y) // y.Q.y |
| |
| t2:=NewFP2copy(E.z) |
| t2.mul(Q.z) |
| t3:=NewFP2copy(E.x) |
| t3.add(E.y); t3.norm() //t3=X1+Y1 |
| t4:=NewFP2copy(Q.x) |
| t4.add(Q.y); t4.norm() //t4=X2+Y2 |
| t3.mul(t4) //t3=(X1+Y1)(X2+Y2) |
| t4.copy(t0); t4.add(t1) //t4=X1.X2+Y1.Y2 |
| |
| t3.sub(t4); t3.norm(); |
| if SEXTIC_TWIST == D_TYPE { |
| t3.mul_ip(); t3.norm() //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1 |
| } |
| t4.copy(E.y); |
| t4.add(E.z); t4.norm() //t4=Y1+Z1 |
| x3:=NewFP2copy(Q.y) |
| x3.add(Q.z); x3.norm() //x3=Y2+Z2 |
| |
| t4.mul(x3) //t4=(Y1+Z1)(Y2+Z2) |
| x3.copy(t1) // |
| x3.add(t2) //X3=Y1.Y2+Z1.Z2 |
| |
| t4.sub(x3); t4.norm(); |
| if SEXTIC_TWIST == D_TYPE { |
| t4.mul_ip(); t4.norm() //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1 |
| } |
| x3.copy(E.x); x3.add(E.z); x3.norm() // x3=X1+Z1 |
| y3:=NewFP2copy(Q.x) |
| y3.add(Q.z); y3.norm() // y3=X2+Z2 |
| x3.mul(y3) // x3=(X1+Z1)(X2+Z2) |
| y3.copy(t0) |
| y3.add(t2) // y3=X1.X2+Z1+Z2 |
| y3.rsub(x3); y3.norm() // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1 |
| |
| if SEXTIC_TWIST == D_TYPE { |
| t0.mul_ip(); t0.norm() // x.Q.x |
| t1.mul_ip(); t1.norm() // y.Q.y |
| } |
| x3.copy(t0); x3.add(t0) |
| t0.add(x3); t0.norm() |
| t2.imul(b) |
| if SEXTIC_TWIST == M_TYPE { |
| t2.mul_ip(); t2.norm() |
| } |
| z3:=NewFP2copy(t1); z3.add(t2); z3.norm() |
| t1.sub(t2); t1.norm() |
| y3.imul(b) |
| if SEXTIC_TWIST == M_TYPE { |
| y3.mul_ip() |
| y3.norm() |
| } |
| 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() |
| |
| return 0 |
| } |
| |
| /* set this-=Q */ |
| func (E *ECP2) Sub(Q *ECP2) int { |
| NQ:=NewECP2(); NQ.Copy(Q) |
| NQ.neg() |
| D:=E.Add(NQ) |
| //Q.neg() |
| return D |
| } |
| /* set this*=q, where q is Modulus, using Frobenius */ |
| func (E *ECP2) frob(X *FP2) { |
| // if E.INF {return} |
| X2:=NewFP2copy(X) |
| X2.sqr() |
| E.x.conj() |
| E.y.conj() |
| E.z.conj() |
| E.z.reduce(); |
| E.x.mul(X2) |
| E.y.mul(X2) |
| E.y.mul(X) |
| } |
| |
| /* P*=e */ |
| func (E *ECP2) mul(e *BIG) *ECP2 { |
| /* fixed size windows */ |
| mt:=NewBIG() |
| t:=NewBIG() |
| P:=NewECP2() |
| Q:=NewECP2() |
| C:=NewECP2() |
| |
| if E.Is_infinity() {return NewECP2()} |
| |
| var W []*ECP2 |
| var w [1+(NLEN*int(BASEBITS)+3)/4]int8 |
| |
| //E.Affine() |
| |
| /* precompute table */ |
| Q.Copy(E) |
| Q.dbl() |
| |
| W=append(W,NewECP2()) |
| W[0].Copy(E); |
| |
| for i:=1;i<8;i++ { |
| W=append(W,NewECP2()) |
| 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[(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) |
| P.Affine() |
| return P |
| } |
| |
| /* Public version */ |
| func (E *ECP2) Mul(e *BIG) *ECP2 { |
| return E.mul(e) |
| } |
| |
| /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */ |
| // Bos & Costello https://eprint.iacr.org/2013/458.pdf |
| // Faz-Hernandez & Longa & Sanchez https://eprint.iacr.org/2013/158.pdf |
| // Side channel attack secure |
| func mul4(Q []*ECP2,u []*BIG) *ECP2 { |
| W:=NewECP2() |
| P:=NewECP2() |
| var T [] *ECP2 |
| mt:=NewBIG() |
| var t [] *BIG |
| |
| var w [NLEN*int(BASEBITS)+1]int8 |
| var s [NLEN*int(BASEBITS)+1]int8 |
| |
| for i:=0;i<4;i++ { |
| t=append(t,NewBIGcopy(u[i])); |
| //Q[i].Affine(); |
| } |
| |
| T=append(T,NewECP2()); T[0].Copy(Q[0]) // Q[0] |
| T=append(T,NewECP2()); T[1].Copy(T[0]); T[1].Add(Q[1]) // Q[0]+Q[1] |
| T=append(T,NewECP2()); T[2].Copy(T[0]); T[2].Add(Q[2]) // Q[0]+Q[2] |
| T=append(T,NewECP2()); T[3].Copy(T[1]); T[3].Add(Q[2]) // Q[0]+Q[1]+Q[2] |
| T=append(T,NewECP2()); T[4].Copy(T[0]); T[4].Add(Q[3]) // Q[0]+Q[3] |
| T=append(T,NewECP2()); T[5].Copy(T[1]); T[5].Add(Q[3]) // Q[0]+Q[1]+Q[3] |
| T=append(T,NewECP2()); T[6].Copy(T[2]); T[6].Add(Q[3]) // Q[0]+Q[2]+Q[3] |
| T=append(T,NewECP2()); T[7].Copy(T[3]); T[7].Add(Q[3]) // Q[0]+Q[1]+Q[2]+Q[3] |
| |
| // Make it odd |
| pb:=1-t[0].parity() |
| t[0].inc(pb) |
| // t[0].norm(); |
| |
| // Number of bits |
| mt.zero() |
| for i:=0;i<4;i++ { |
| t[i].norm() |
| mt.or(t[i]) |
| } |
| |
| nb:=1+mt.nbits(); |
| |
| // Sign pivot |
| s[nb-1]=1 |
| for i:=0;i<nb-1;i++ { |
| t[0].fshr(1) |
| s[i]=2*int8(t[0].parity())-1 |
| } |
| |
| // Recoded exponent |
| for i:=0; i<nb; i++ { |
| w[i]=0 |
| k:=1 |
| for j:=1; j<4; j++ { |
| bt:=s[i]*int8(t[j].parity()) |
| t[j].fshr(1) |
| t[j].dec(int(bt)>>1) |
| t[j].norm() |
| w[i]+=bt*int8(k) |
| k*=2 |
| } |
| } |
| |
| // Main loop |
| P.selector(T,int32(2*w[nb-1]+1)) |
| for i:=nb-2;i>=0;i-- { |
| P.dbl() |
| W.selector(T,int32(2*w[i]+s[i])) |
| P.Add(W) |
| } |
| |
| // apply correction |
| W.Copy(P) |
| W.Sub(Q[0]) |
| P.cmove(W,pb) |
| |
| P.Affine() |
| return P |
| } |
| |
| /* |
| func mul4(Q []*ECP2,u []*BIG) *ECP2 { |
| var a [4]int8 |
| T:=NewECP2() |
| C:=NewECP2() |
| P:=NewECP2() |
| |
| var W [] *ECP2 |
| |
| mt:=NewBIG() |
| var t []*BIG |
| |
| var w [NLEN*int(BASEBITS)+1]int8 |
| |
| for i:=0;i<4;i++ { |
| t=append(t,NewBIGcopy(u[i])); |
| Q[i].Affine(); |
| } |
| |
| // precompute table |
| |
| W=append(W,NewECP2()); W[0].Copy(Q[0]); W[0].Sub(Q[1]) |
| W=append(W,NewECP2()); W[1].Copy(W[0]) |
| W=append(W,NewECP2()); W[2].Copy(W[0]) |
| W=append(W,NewECP2()); W[3].Copy(W[0]) |
| W=append(W,NewECP2()); W[4].Copy(Q[0]); W[4].Add(Q[1]) |
| W=append(W,NewECP2()); W[5].Copy(W[4]) |
| W=append(W,NewECP2()); W[6].Copy(W[4]) |
| W=append(W,NewECP2()); W[7].Copy(W[4]) |
| |
| T.Copy(Q[2]); T.Sub(Q[3]) |
| W[1].Sub(T) |
| W[2].Add(T) |
| W[5].Sub(T) |
| W[6].Add(T) |
| T.Copy(Q[2]); T.Add(Q[3]) |
| W[0].Sub(T) |
| W[3].Add(T) |
| W[4].Sub(T) |
| W[7].Add(T) |
| |
| // if multiplier is even add 1 to multiplier, and add P to correction |
| mt.zero(); C.inf() |
| for i:=0;i<4;i++ { |
| if t[i].parity()==0 { |
| t[i].inc(1); t[i].norm() |
| C.Add(Q[i]) |
| } |
| mt.add(t[i]); mt.norm() |
| } |
| |
| nb:=1+mt.nbits(); |
| |
| // convert exponent to signed 1-bit window |
| for j:=0;j<nb;j++ { |
| for i:=0;i<4;i++ { |
| a[i]=int8(t[i].lastbits(2)-2) |
| t[i].dec(int(a[i])); t[i].norm() |
| t[i].fshr(1) |
| } |
| w[j]=(8*a[0]+4*a[1]+2*a[2]+a[3]) |
| } |
| w[nb]=int8(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2)) |
| |
| P.Copy(W[(w[nb]-1)/2]) |
| for i:=nb-1;i>=0;i-- { |
| T.selector(W,int32(w[i])) |
| P.dbl() |
| P.Add(T) |
| } |
| P.Sub(C) // apply correction |
| |
| P.Affine() |
| return P |
| } |
| */ |
| |
| /* needed for SOK */ |
| func ECP2_mapit(h []byte) *ECP2 { |
| q:=NewBIGints(Modulus) |
| x:=FromBytes(h[:]) |
| one:=NewBIGint(1) |
| var X *FP2 |
| var Q,T,K,xQ,x2Q *ECP2 |
| x.Mod(q) |
| for true { |
| X=NewFP2bigs(one,x) |
| Q=NewECP2fp2(X) |
| if !Q.Is_infinity() {break} |
| x.inc(1); x.norm() |
| } |
| /* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */ |
| Fra:=NewBIGints(Fra) |
| Frb:=NewBIGints(Frb) |
| X=NewFP2bigs(Fra,Frb) |
| if SEXTIC_TWIST == M_TYPE { |
| X.inverse() |
| X.norm() |
| } |
| |
| x=NewBIGints(CURVE_Bnx) |
| |
| if CURVE_PAIRING_TYPE==BN { |
| T=NewECP2(); T.Copy(Q) |
| T=T.mul(x); |
| if SIGN_OF_X==NEGATIVEX { |
| T.neg() |
| } |
| |
| K=NewECP2(); K.Copy(T) |
| K.dbl(); K.Add(T); //K.Affine() |
| |
| K.frob(X) |
| Q.frob(X); Q.frob(X); Q.frob(X) |
| Q.Add(T); Q.Add(K) |
| T.frob(X); T.frob(X) |
| Q.Add(T) |
| } |
| if CURVE_PAIRING_TYPE==BLS { |
| // xQ=NewECP2() |
| // x2Q=NewECP2() |
| |
| xQ=Q.mul(x) |
| x2Q=xQ.mul(x) |
| |
| if SIGN_OF_X==NEGATIVEX { |
| xQ.neg() |
| } |
| |
| x2Q.Sub(xQ) |
| x2Q.Sub(Q) |
| |
| xQ.Sub(Q) |
| xQ.frob(X) |
| |
| Q.dbl() |
| Q.frob(X) |
| Q.frob(X) |
| |
| Q.Add(x2Q) |
| Q.Add(xQ) |
| } |
| Q.Affine() |
| return Q |
| } |
| |
| func ECP2_generator() *ECP2 { |
| var G *ECP2 |
| G=NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa),NewBIGints(CURVE_Pxb)),NewFP2bigs(NewBIGints(CURVE_Pya),NewBIGints(CURVE_Pyb))) |
| return G |
| } |