| /* |
| 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. |
| */ |
| |
| /* AMCL Weierstrass elliptic curve functions over FP4 */ |
| |
| package org.apache.milagro.amcl.XXX; |
| |
| public final class ECP4 { |
| private FP4 x; |
| private FP4 y; |
| private FP4 z; |
| |
| /* Constructor - set this=O */ |
| public ECP4() { |
| x=new FP4(0); |
| y=new FP4(1); |
| z=new FP4(0); |
| } |
| |
| public ECP4(ECP4 e) { |
| this.x = new FP4(e.x); |
| this.y = new FP4(e.y); |
| this.z = new FP4(e.z); |
| } |
| |
| /* Test this=O? */ |
| public boolean is_infinity() { |
| return (x.iszilch() && z.iszilch()); |
| } |
| /* copy this=P */ |
| public void copy(ECP4 P) |
| { |
| x.copy(P.x); |
| y.copy(P.y); |
| z.copy(P.z); |
| } |
| /* set this=O */ |
| public void inf() { |
| x.zero(); |
| y.one(); |
| z.zero(); |
| } |
| |
| /* Conditional move of Q to P dependant on d */ |
| public void cmove(ECP4 Q,int d) |
| { |
| x.cmove(Q.x,d); |
| y.cmove(Q.y,d); |
| z.cmove(Q.z,d); |
| } |
| |
| /* return 1 if b==c, no branching */ |
| public static int teq(int b,int c) |
| { |
| int x=b^c; |
| x-=1; // if x=0, x now -1 |
| return ((x>>31)&1); |
| } |
| |
| /* Constant time select from pre-computed table */ |
| public void select(ECP4 W[],int b) |
| { |
| ECP4 MP=new ECP4(); |
| int m=b>>31; |
| int babs=(b^m)-m; |
| |
| babs=(babs-1)/2; |
| |
| cmove(W[0],teq(babs,0)); // conditional move |
| cmove(W[1],teq(babs,1)); |
| cmove(W[2],teq(babs,2)); |
| cmove(W[3],teq(babs,3)); |
| cmove(W[4],teq(babs,4)); |
| cmove(W[5],teq(babs,5)); |
| cmove(W[6],teq(babs,6)); |
| cmove(W[7],teq(babs,7)); |
| |
| MP.copy(this); |
| MP.neg(); |
| cmove(MP,(int)(m&1)); |
| } |
| |
| /* Test if P == Q */ |
| public boolean equals(ECP4 Q) { |
| |
| FP4 a=new FP4(x); // ***** |
| FP4 b=new FP4(Q.x); |
| a.mul(Q.z); |
| b.mul(z); |
| if (!a.equals(b)) return false; |
| |
| a.copy(y); a.mul(Q.z); |
| b.copy(Q.y); b.mul(z); |
| if (!a.equals(b)) return false; |
| |
| return true; |
| } |
| /* set this=-this */ |
| public void neg() { |
| // if (is_infinity()) return; |
| y.norm(); |
| y.neg(); y.norm(); |
| return; |
| } |
| /* set to Affine - (x,y,z) to (x,y) */ |
| public void affine() { |
| if (is_infinity()) return; |
| FP4 one=new FP4(1); |
| if (z.equals(one)) |
| { |
| x.reduce(); |
| y.reduce(); |
| return; |
| } |
| z.inverse(); |
| |
| x.mul(z); x.reduce(); // ***** |
| y.mul(z); y.reduce(); |
| z.copy(one); |
| } |
| |
| /* extract affine x as FP4 */ |
| public FP4 getX() |
| { |
| ECP4 W= new ECP4(this); |
| W.affine(); |
| return W.x; |
| } |
| /* extract affine y as FP4 */ |
| public FP4 getY() |
| { |
| ECP4 W= new ECP4(this); |
| W.affine(); |
| return W.y; |
| } |
| /* extract projective x */ |
| public FP4 getx() |
| { |
| return x; |
| } |
| /* extract projective y */ |
| public FP4 gety() |
| { |
| return y; |
| } |
| /* extract projective z */ |
| public FP4 getz() |
| { |
| return z; |
| } |
| |
| /* convert to byte array */ |
| public void toBytes(byte[] b) |
| { |
| byte[] t=new byte[CONFIG_BIG.MODBYTES]; |
| ECP4 W=new ECP4(this); |
| int MB=CONFIG_BIG.MODBYTES; |
| |
| W.x.geta().getA().toBytes(t); |
| for (int i=0;i<MB;i++) |
| b[i]=t[i]; |
| W.x.geta().getB().toBytes(t); |
| for (int i=0;i<MB;i++) |
| b[i+MB]=t[i]; |
| W.x.getb().getA().toBytes(t); |
| for (int i=0;i<MB;i++) |
| b[i+2*MB]=t[i]; |
| W.x.getb().getB().toBytes(t); |
| for (int i=0;i<MB;i++) |
| b[i+3*MB]=t[i]; |
| |
| W.y.geta().getA().toBytes(t); |
| for (int i=0;i<MB;i++) |
| b[i+4*MB]=t[i]; |
| W.y.geta().getB().toBytes(t); |
| for (int i=0;i<MB;i++) |
| b[i+5*MB]=t[i]; |
| W.y.getb().getA().toBytes(t); |
| for (int i=0;i<MB;i++) |
| b[i+6*MB]=t[i]; |
| W.y.getb().getB().toBytes(t); |
| for (int i=0;i<MB;i++) |
| b[i+7*MB]=t[i]; |
| |
| } |
| |
| /* convert from byte array to point */ |
| public static ECP4 fromBytes(byte[] b) |
| { |
| byte[] t=new byte[CONFIG_BIG.MODBYTES]; |
| BIG ra; |
| BIG rb; |
| int MB=CONFIG_BIG.MODBYTES; |
| |
| for (int i=0;i<MB;i++) {t[i]=b[i];} |
| ra=BIG.fromBytes(t); |
| for (int i=0;i<MB;i++) {t[i]=b[i+MB];} |
| rb=BIG.fromBytes(t); |
| |
| FP2 ra4=new FP2(ra,rb); |
| |
| for (int i=0;i<MB;i++) {t[i]=b[i+2*MB];} |
| ra=BIG.fromBytes(t); |
| for (int i=0;i<MB;i++) {t[i]=b[i+3*MB];} |
| rb=BIG.fromBytes(t); |
| |
| FP2 rb4=new FP2(ra,rb); |
| |
| FP4 rx=new FP4(ra4,rb4); |
| |
| for (int i=0;i<MB;i++) {t[i]=b[i+4*MB];} |
| ra=BIG.fromBytes(t); |
| for (int i=0;i<MB;i++) {t[i]=b[i+5*MB];} |
| rb=BIG.fromBytes(t); |
| |
| ra4=new FP2(ra,rb); |
| |
| for (int i=0;i<MB;i++) {t[i]=b[i+6*MB];} |
| ra=BIG.fromBytes(t); |
| for (int i=0;i<MB;i++) {t[i]=b[i+7*MB];} |
| rb=BIG.fromBytes(t); |
| |
| rb4=new FP2(ra,rb); |
| FP4 ry=new FP4(ra4,rb4); |
| |
| |
| return new ECP4(rx,ry); |
| } |
| |
| /* convert this to hex string */ |
| public String toString() { |
| ECP4 W=new ECP4(this); |
| 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 */ |
| public static FP4 RHS(FP4 x) { |
| FP4 r=new FP4(x); |
| r.sqr(); |
| FP4 b=new FP4(new FP2(new BIG(ROM.CURVE_B))); |
| |
| if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.D_TYPE) |
| { |
| b.div_i(); |
| } |
| if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.M_TYPE) |
| { |
| b.times_i(); |
| } |
| |
| r.mul(x); |
| r.add(b); |
| |
| r.reduce(); |
| return r; |
| } |
| |
| /* construct this from (x,y) - but set to O if not on curve */ |
| public ECP4(FP4 ix,FP4 iy) { |
| x=new FP4(ix); |
| y=new FP4(iy); |
| z=new FP4(1); |
| x.norm(); |
| FP4 rhs=RHS(x); |
| FP4 y2=new FP4(y); |
| y2.sqr(); |
| if (!y2.equals(rhs)) inf(); |
| } |
| |
| /* construct this from x - but set to O if not on curve */ |
| public ECP4(FP4 ix) { |
| x=new FP4(ix); |
| y=new FP4(1); |
| z=new FP4(1); |
| x.norm(); |
| FP4 rhs=RHS(x); |
| if (rhs.sqrt()) |
| { |
| y.copy(rhs); |
| } |
| else {inf(); } |
| } |
| |
| /* this+=this */ |
| public int dbl() { |
| |
| FP4 iy=new FP4(y); |
| if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.D_TYPE) |
| { |
| iy.times_i(); |
| } |
| FP4 t0=new FP4(y); //***** Change |
| t0.sqr(); |
| if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.D_TYPE) |
| { |
| t0.times_i(); |
| } |
| FP4 t1=new FP4(iy); |
| t1.mul(z); |
| FP4 t2=new FP4(z); |
| t2.sqr(); |
| |
| z.copy(t0); |
| z.add(t0); z.norm(); |
| z.add(z); |
| z.add(z); |
| z.norm(); |
| |
| t2.imul(3*ROM.CURVE_B_I); |
| if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.M_TYPE) |
| { |
| t2.times_i(); |
| //t2.norm(); |
| } |
| |
| FP4 x3=new FP4(t2); |
| x3.mul(z); |
| |
| FP4 y3=new FP4(t0); |
| |
| y3.add(t2); y3.norm(); |
| 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(x); t1.mul(iy); // |
| x.copy(t0); x.norm(); x.mul(t1); x.add(x); //(y^2-9bz^2)xy2 |
| |
| x.norm(); |
| y.copy(y3); y.norm(); |
| |
| return 1; |
| } |
| |
| /* this+=Q - return 0 for add, 1 for double, -1 for O */ |
| public int add(ECP4 Q) { |
| |
| int b=3*ROM.CURVE_B_I; |
| FP4 t0=new FP4(x); |
| t0.mul(Q.x); // x.Q.x |
| FP4 t1=new FP4(y); |
| t1.mul(Q.y); // y.Q.y |
| |
| FP4 t2=new FP4(z); |
| t2.mul(Q.z); |
| FP4 t3=new FP4(x); |
| t3.add(y); t3.norm(); //t3=X1+Y1 |
| FP4 t4=new FP4(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 (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.D_TYPE) |
| { |
| t3.times_i(); //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1 |
| } |
| t4.copy(y); |
| t4.add(z); t4.norm(); //t4=Y1+Z1 |
| FP4 x3=new FP4(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 (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.D_TYPE) |
| { |
| t4.times_i(); //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1 |
| } |
| x3.copy(x); x3.add(z); x3.norm(); // x3=X1+Z1 |
| FP4 y3=new FP4(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 (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.D_TYPE) |
| { |
| t0.times_i(); // x.Q.x |
| t1.times_i(); // y.Q.y |
| } |
| x3.copy(t0); x3.add(t0); |
| t0.add(x3); t0.norm(); |
| t2.imul(b); |
| if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.M_TYPE) |
| { |
| t2.times_i(); |
| } |
| FP4 z3=new FP4(t1); z3.add(t2); z3.norm(); |
| t1.sub(t2); t1.norm(); |
| y3.imul(b); |
| if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.M_TYPE) |
| { |
| y3.times_i(); |
| } |
| 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); |
| |
| x.copy(x3); x.norm(); |
| y.copy(y3); y.norm(); |
| z.copy(z3); z.norm(); |
| |
| return 0; |
| } |
| |
| /* set this-=Q */ |
| public int sub(ECP4 Q) { |
| ECP4 NQ=new ECP4(Q); |
| NQ.neg(); |
| int D=add(NQ); |
| |
| return D; |
| } |
| |
| public static FP2[] frob_constants() { |
| BIG Fra=new BIG(ROM.Fra); |
| BIG Frb=new BIG(ROM.Frb); |
| FP2 X=new FP2(Fra,Frb); |
| |
| FP2 F0=new FP2(X); F0.sqr(); |
| FP2 F2=new FP2(F0); |
| F2.mul_ip(); F2.norm(); |
| FP2 F1=new FP2(F2); F1.sqr(); |
| F2.mul(F1); |
| F1.copy(X); |
| if (CONFIG_CURVE.SEXTIC_TWIST == CONFIG_CURVE.M_TYPE) |
| { |
| F1.mul_ip(); |
| F1.inverse(); |
| F0.copy(F1); F0.sqr(); |
| } |
| F0.mul_ip(); F0.norm(); |
| F1.mul(F0); |
| FP2[] F={F0,F1,F2}; |
| return F; |
| } |
| |
| |
| /* set this*=q, where q is Modulus, using Frobenius */ |
| public void frob(FP2 F[],int n) |
| { |
| for (int i=0;i<n;i++) { |
| x.frob(F[2]); |
| x.pmul(F[0]); |
| |
| y.frob(F[2]); |
| y.pmul(F[1]); |
| y.times_i(); |
| |
| z.frob(F[2]); |
| } |
| } |
| |
| /* P*=e */ |
| public ECP4 mul(BIG e) |
| { |
| /* fixed size windows */ |
| int i,b,nb,m,s,ns; |
| BIG mt=new BIG(); |
| BIG t=new BIG(); |
| ECP4 P=new ECP4(); |
| ECP4 Q=new ECP4(); |
| ECP4 C=new ECP4(); |
| ECP4[] W=new ECP4[8]; |
| byte[] w=new byte[1+(BIG.NLEN*CONFIG_BIG.BASEBITS+3)/4]; |
| |
| if (is_infinity()) return new ECP4(); |
| |
| /* precompute table */ |
| Q.copy(this); |
| Q.dbl(); |
| W[0]=new ECP4(); |
| W[0].copy(this); |
| |
| for (i=1;i<8;i++) |
| { |
| W[i]=new ECP4(); |
| W[i].copy(W[i-1]); |
| W[i].add(Q); |
| } |
| |
| /* make exponent odd - add 2P if even, P if odd */ |
| t.copy(e); |
| s=t.parity(); |
| t.inc(1); t.norm(); ns=t.parity(); mt.copy(t); mt.inc(1); mt.norm(); |
| t.cmove(mt,s); |
| Q.cmove(this,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]=(byte)(t.lastbits(5)-16); |
| t.dec(w[i]); t.norm(); |
| t.fshr(4); |
| } |
| w[nb]=(byte)t.lastbits(5); |
| |
| P.copy(W[(w[nb]-1)/2]); |
| for (i=nb-1;i>=0;i--) |
| { |
| Q.select(W,w[i]); |
| P.dbl(); |
| P.dbl(); |
| P.dbl(); |
| P.dbl(); |
| P.add(Q); |
| } |
| P.sub(C); |
| P.affine(); |
| return P; |
| } |
| |
| /* 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 |
| |
| public static ECP4 mul8(ECP4[] Q,BIG[] u) |
| { |
| int i,j,k,nb,pb1,pb2; |
| ECP4 W=new ECP4(); |
| ECP4 P=new ECP4(); |
| ECP4[] T1=new ECP4[8]; |
| ECP4[] T2=new ECP4[8]; |
| |
| |
| BIG mt=new BIG(); |
| BIG[] t=new BIG[8]; |
| |
| byte[] w1=new byte[BIG.NLEN*CONFIG_BIG.BASEBITS+1]; |
| byte[] s1=new byte[BIG.NLEN*CONFIG_BIG.BASEBITS+1]; |
| byte[] w2=new byte[BIG.NLEN*CONFIG_BIG.BASEBITS+1]; |
| byte[] s2=new byte[BIG.NLEN*CONFIG_BIG.BASEBITS+1]; |
| |
| for (i=0;i<8;i++) |
| { |
| t[i]=new BIG(u[i]); |
| //Q[i].affine(); |
| t[i].norm(); |
| } |
| |
| T1[0] = new ECP4(); T1[0].copy(Q[0]); // Q[0] |
| T1[1] = new ECP4(); T1[1].copy(T1[0]); T1[1].add(Q[1]); // Q[0]+Q[1] |
| T1[2] = new ECP4(); T1[2].copy(T1[0]); T1[2].add(Q[2]); // Q[0]+Q[2] |
| T1[3] = new ECP4(); T1[3].copy(T1[1]); T1[3].add(Q[2]); // Q[0]+Q[1]+Q[2] |
| T1[4] = new ECP4(); T1[4].copy(T1[0]); T1[4].add(Q[3]); // Q[0]+Q[3] |
| T1[5] = new ECP4(); T1[5].copy(T1[1]); T1[5].add(Q[3]); // Q[0]+Q[1]+Q[3] |
| T1[6] = new ECP4(); T1[6].copy(T1[2]); T1[6].add(Q[3]); // Q[0]+Q[2]+Q[3] |
| T1[7] = new ECP4(); T1[7].copy(T1[3]); T1[7].add(Q[3]); // Q[0]+Q[1]+Q[2]+Q[3] |
| |
| // Use Frobenius |
| FP2[] F=ECP4.frob_constants(); |
| |
| for (i=0;i<8;i++) { |
| T2[i] = new ECP4(); T2[i].copy(T1[i]); |
| T2[i].frob(F,4); |
| } |
| |
| // Make it odd |
| pb1=1-t[0].parity(); |
| t[0].inc(pb1); |
| t[0].norm(); |
| |
| pb2=1-t[4].parity(); |
| t[4].inc(pb2); |
| t[4].norm(); |
| |
| |
| // Number of bits |
| mt.zero(); |
| for (i=0;i<8;i++) { |
| mt.or(t[i]); |
| } |
| nb=1+mt.nbits(); |
| |
| // Sign pivot |
| s1[nb-1]=1; |
| s2[nb-1]=1; |
| for (i=0;i<nb-1;i++) { |
| t[0].fshr(1); |
| s1[i]=(byte)(2*t[0].parity()-1); |
| t[4].fshr(1); |
| s2[i]=(byte)(2*t[4].parity()-1); |
| } |
| |
| // Recoded exponent |
| for (i=0; i<nb; i++) { |
| w1[i]=0; |
| k=1; |
| for (j=1; j<4; j++) { |
| byte bt=(byte)(s1[i]*t[j].parity()); |
| t[j].fshr(1); |
| t[j].dec((int)(bt)>>1); |
| t[j].norm(); |
| w1[i]+=bt*(byte)k; |
| k*=2; |
| } |
| |
| w2[i]=0; |
| k=1; |
| for (j=5; j<8; j++) { |
| byte bt=(byte)(s2[i]*t[j].parity()); |
| t[j].fshr(1); |
| t[j].dec((int)(bt)>>1); |
| t[j].norm(); |
| w2[i]+=bt*(byte)k; |
| k*=2; |
| } |
| } |
| |
| // Main loop |
| P.select(T1,(int)(2*w1[nb-1]+1)); |
| W.select(T2,(int)(2*w2[nb-1]+1)); |
| P.add(W); |
| for (i=nb-2;i>=0;i--) { |
| P.dbl(); |
| W.select(T1,(int)(2*w1[i]+s1[i])); |
| P.add(W); |
| W.select(T2,(int)(2*w2[i]+s2[i])); |
| P.add(W); |
| |
| } |
| |
| // apply correction |
| W.copy(P); |
| W.sub(Q[0]); |
| P.cmove(W,pb1); |
| |
| W.copy(P); |
| W.sub(Q[4]); |
| P.cmove(W,pb2); |
| |
| P.affine(); |
| return P; |
| } |
| |
| /* needed for SOK */ |
| public static ECP4 mapit(byte[] h) |
| { |
| BIG q=new BIG(ROM.Modulus); |
| BIG x=BIG.fromBytes(h); |
| BIG one=new BIG(1); |
| FP4 X; |
| FP2 X2; |
| ECP4 Q; |
| x.mod(q); |
| while (true) |
| { |
| X2=new FP2(one,x); |
| X=new FP4(X2); |
| Q=new ECP4(X); |
| if (!Q.is_infinity()) break; |
| x.inc(1); x.norm(); |
| } |
| |
| FP2[] F=ECP4.frob_constants(); |
| x=new BIG(ROM.CURVE_Bnx); |
| |
| /* Efficient hash maps to G2 on BLS curves - Budroni, Pintore */ |
| |
| ECP4 xQ=Q.mul(x); |
| ECP4 x2Q=xQ.mul(x); |
| ECP4 x3Q=x2Q.mul(x); |
| ECP4 x4Q=x3Q.mul(x); |
| |
| if (CONFIG_CURVE.SIGN_OF_X==CONFIG_CURVE.NEGATIVEX) |
| { |
| xQ.neg(); |
| x3Q.neg(); |
| } |
| |
| x4Q.sub(x3Q); |
| x4Q.sub(Q); |
| |
| x3Q.sub(x2Q); |
| x3Q.frob(F,1); |
| |
| x2Q.sub(xQ); |
| x2Q.frob(F,2); |
| |
| xQ.sub(Q); |
| xQ.frob(F,3); |
| |
| Q.dbl(); |
| Q.frob(F,4); |
| |
| Q.add(x4Q); |
| Q.add(x3Q); |
| Q.add(x2Q); |
| Q.add(xQ); |
| |
| Q.affine(); |
| return Q; |
| } |
| |
| public static ECP4 generator() |
| { |
| |
| return new ECP4( |
| new FP4( |
| new FP2( |
| new BIG(ROM.CURVE_Pxaa),new BIG(ROM.CURVE_Pxab)), |
| new FP2( |
| new BIG(ROM.CURVE_Pxba),new BIG(ROM.CURVE_Pxbb))), |
| new FP4( |
| new FP2( |
| new BIG(ROM.CURVE_Pyaa),new BIG(ROM.CURVE_Pyab)), |
| new FP2( |
| new BIG(ROM.CURVE_Pyba),new BIG(ROM.CURVE_Pybb)))); |
| } |
| |
| } |