| /* |
| 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 FP2 */ |
| |
| package org.apache.milagro.amcl.BN254CX; |
| |
| public final class ECP2 { |
| private FP2 x; |
| private FP2 y; |
| private FP2 z; |
| // private boolean INF; |
| |
| /* Constructor - set this=O */ |
| public ECP2() { |
| // INF=true; |
| x=new FP2(0); |
| y=new FP2(1); |
| z=new FP2(0); |
| } |
| |
| public ECP2(ECP2 e) { |
| this.x = new FP2(e.x); |
| this.y = new FP2(e.y); |
| this.z = new FP2(e.z); |
| } |
| |
| /* Test this=O? */ |
| public boolean is_infinity() { |
| // if (INF) return true; //****** |
| return (x.iszilch() && z.iszilch()); |
| } |
| /* copy this=P */ |
| public void copy(ECP2 P) |
| { |
| x.copy(P.x); |
| y.copy(P.y); |
| z.copy(P.z); |
| // INF=P.INF; |
| } |
| /* set this=O */ |
| public void inf() { |
| // INF=true; |
| x.zero(); |
| y.one(); |
| z.zero(); |
| } |
| |
| /* Conditional move of Q to P dependant on d */ |
| public void cmove(ECP2 Q,int d) |
| { |
| x.cmove(Q.x,d); |
| y.cmove(Q.y,d); |
| z.cmove(Q.z,d); |
| |
| // boolean bd; |
| // if (d==0) bd=false; |
| // else bd=true; |
| // INF^=(INF^Q.INF)&bd; |
| } |
| |
| /* 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(ECP2 W[],int b) |
| { |
| ECP2 MP=new ECP2(); |
| 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(ECP2 Q) { |
| // if (is_infinity() && Q.is_infinity()) return true; |
| // if (is_infinity() || Q.is_infinity()) return false; |
| |
| |
| FP2 a=new FP2(x); // ***** |
| FP2 b=new FP2(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; |
| FP2 one=new FP2(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 FP2 */ |
| public FP2 getX() |
| { |
| ECP2 W=new ECP2(this); |
| W.affine(); |
| return W.x; |
| } |
| /* extract affine y as FP2 */ |
| public FP2 getY() |
| { |
| ECP2 W=new ECP2(this); |
| W.affine(); |
| return W.y; |
| } |
| /* extract projective x */ |
| public FP2 getx() |
| { |
| return x; |
| } |
| /* extract projective y */ |
| public FP2 gety() |
| { |
| return y; |
| } |
| /* extract projective z */ |
| public FP2 getz() |
| { |
| return z; |
| } |
| /* convert to byte array */ |
| public void toBytes(byte[] b) |
| { |
| byte[] t=new byte[BIG.MODBYTES]; |
| ECP2 W=new ECP2(this); |
| W.affine(); |
| W.x.getA().toBytes(t); |
| for (int i=0;i<BIG.MODBYTES;i++) |
| b[i]=t[i]; |
| W.x.getB().toBytes(t); |
| for (int i=0;i<BIG.MODBYTES;i++) |
| b[i+BIG.MODBYTES]=t[i]; |
| |
| W.y.getA().toBytes(t); |
| for (int i=0;i<BIG.MODBYTES;i++) |
| b[i+2*BIG.MODBYTES]=t[i]; |
| W.y.getB().toBytes(t); |
| for (int i=0;i<BIG.MODBYTES;i++) |
| b[i+3*BIG.MODBYTES]=t[i]; |
| } |
| /* convert from byte array to point */ |
| public static ECP2 fromBytes(byte[] b) |
| { |
| byte[] t=new byte[BIG.MODBYTES]; |
| BIG ra; |
| BIG rb; |
| |
| for (int i=0;i<BIG.MODBYTES;i++) t[i]=b[i]; |
| ra=BIG.fromBytes(t); |
| for (int i=0;i<BIG.MODBYTES;i++) t[i]=b[i+BIG.MODBYTES]; |
| rb=BIG.fromBytes(t); |
| FP2 rx=new FP2(ra,rb); |
| |
| for (int i=0;i<BIG.MODBYTES;i++) t[i]=b[i+2*BIG.MODBYTES]; |
| ra=BIG.fromBytes(t); |
| for (int i=0;i<BIG.MODBYTES;i++) t[i]=b[i+3*BIG.MODBYTES]; |
| rb=BIG.fromBytes(t); |
| FP2 ry=new FP2(ra,rb); |
| |
| return new ECP2(rx,ry); |
| } |
| /* convert this to hex string */ |
| public String toString() { |
| ECP2 W=new ECP2(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 FP2 RHS(FP2 x) { |
| x.norm(); |
| FP2 r=new FP2(x); |
| r.sqr(); |
| FP2 b=new FP2(new BIG(ROM.CURVE_B)); |
| |
| if (ECP.SEXTIC_TWIST==ECP.D_TYPE) |
| { |
| b.div_ip(); |
| } |
| if (ECP.SEXTIC_TWIST==ECP.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 */ |
| public ECP2(FP2 ix,FP2 iy) { |
| x=new FP2(ix); |
| y=new FP2(iy); |
| z=new FP2(1); |
| FP2 rhs=RHS(x); |
| FP2 y2=new FP2(y); |
| y2.sqr(); |
| if (!y2.equals(rhs)) inf(); |
| // if (y2.equals(rhs)) INF=false; |
| // else {x.zero();INF=true;} |
| } |
| |
| /* construct this from x - but set to O if not on curve */ |
| public ECP2(FP2 ix) { |
| x=new FP2(ix); |
| y=new FP2(1); |
| z=new FP2(1); |
| FP2 rhs=RHS(x); |
| if (rhs.sqrt()) |
| { |
| y.copy(rhs); |
| //INF=false; |
| } |
| else {/*x.zero();INF=true;*/ inf();} |
| } |
| |
| /* this+=this */ |
| public int dbl() { |
| // if (INF) return -1; |
| //System.out.println("Into dbl"); |
| FP2 iy=new FP2(y); |
| if (ECP.SEXTIC_TWIST==ECP.D_TYPE) |
| { |
| iy.mul_ip(); iy.norm(); |
| } |
| FP2 t0=new FP2(y); //***** Change |
| t0.sqr(); |
| if (ECP.SEXTIC_TWIST==ECP.D_TYPE) |
| { |
| t0.mul_ip(); |
| } |
| FP2 t1=new FP2(iy); |
| t1.mul(z); |
| FP2 t2=new FP2(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 (ECP.SEXTIC_TWIST==ECP.M_TYPE) |
| { |
| t2.mul_ip(); |
| t2.norm(); |
| } |
| |
| FP2 x3=new FP2(t2); |
| x3.mul(z); |
| |
| FP2 y3=new FP2(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(); |
| //System.out.println("Out of dbl"); |
| return 1; |
| } |
| |
| /* this+=Q - return 0 for add, 1 for double, -1 for O */ |
| public int add(ECP2 Q) { |
| // if (INF) |
| // { |
| // copy(Q); |
| // return -1; |
| // } |
| // if (Q.INF) return -1; |
| //System.out.println("Into add"); |
| int b=3*ROM.CURVE_B_I; |
| FP2 t0=new FP2(x); |
| t0.mul(Q.x); // x.Q.x |
| FP2 t1=new FP2(y); |
| t1.mul(Q.y); // y.Q.y |
| |
| FP2 t2=new FP2(z); |
| t2.mul(Q.z); |
| FP2 t3=new FP2(x); |
| t3.add(y); t3.norm(); //t3=X1+Y1 |
| FP2 t4=new FP2(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 (ECP.SEXTIC_TWIST==ECP.D_TYPE) |
| { |
| t3.mul_ip(); t3.norm(); //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1 |
| } |
| t4.copy(y); |
| t4.add(z); t4.norm(); //t4=Y1+Z1 |
| FP2 x3=new FP2(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 (ECP.SEXTIC_TWIST==ECP.D_TYPE) |
| { |
| t4.mul_ip(); t4.norm(); //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1 |
| } |
| x3.copy(x); x3.add(z); x3.norm(); // x3=X1+Z1 |
| FP2 y3=new FP2(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 (ECP.SEXTIC_TWIST==ECP.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 (ECP.SEXTIC_TWIST==ECP.M_TYPE) |
| { |
| t2.mul_ip(); t2.norm(); |
| } |
| FP2 z3=new FP2(t1); z3.add(t2); z3.norm(); |
| t1.sub(t2); t1.norm(); |
| y3.imul(b); |
| if (ECP.SEXTIC_TWIST==ECP.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); |
| |
| x.copy(x3); x.norm(); |
| y.copy(y3); y.norm(); |
| z.copy(z3); z.norm(); |
| //System.out.println("Out of add"); |
| return 0; |
| } |
| |
| /* set this-=Q */ |
| public int sub(ECP2 Q) { |
| ECP2 NQ=new ECP2(Q); |
| NQ.neg(); |
| int D=add(NQ); |
| //Q.neg(); |
| //int D=add(Q); |
| //Q.neg(); |
| return D; |
| } |
| /* set this*=q, where q is Modulus, using Frobenius */ |
| public void frob(FP2 X) |
| { |
| // if (INF) return; |
| FP2 X2=new FP2(X); |
| |
| X2.sqr(); |
| x.conj(); |
| y.conj(); |
| z.conj(); |
| z.reduce(); |
| x.mul(X2); |
| |
| y.mul(X2); |
| y.mul(X); |
| } |
| |
| /* P*=e */ |
| public ECP2 mul(BIG e) |
| { |
| /* fixed size windows */ |
| int i,b,nb,m,s,ns; |
| BIG mt=new BIG(); |
| BIG t=new BIG(); |
| ECP2 P=new ECP2(); |
| ECP2 Q=new ECP2(); |
| ECP2 C=new ECP2(); |
| ECP2[] W=new ECP2[8]; |
| byte[] w=new byte[1+(BIG.NLEN*BIG.BASEBITS+3)/4]; |
| |
| if (is_infinity()) return new ECP2(); |
| |
| //affine(); |
| |
| /* precompute table */ |
| Q.copy(this); |
| Q.dbl(); |
| W[0]=new ECP2(); |
| W[0].copy(this); |
| |
| for (i=1;i<8;i++) |
| { |
| W[i]=new ECP2(); |
| 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 ECP2 mul4(ECP2[] Q,BIG[] u) |
| { |
| int i,j,nb,pb; |
| ECP2 W=new ECP2(); |
| ECP2 P=new ECP2(); |
| ECP2[] T=new ECP2[8]; |
| |
| BIG mt=new BIG(); |
| BIG[] t=new BIG[4]; |
| |
| byte[] w=new byte[BIG.NLEN*BIG.BASEBITS+1]; |
| byte[] s=new byte[BIG.NLEN*BIG.BASEBITS+1]; |
| |
| for (i=0;i<4;i++) |
| { |
| t[i]=new BIG(u[i]); |
| t[i].norm(); |
| //Q[i].affine(); |
| } |
| |
| T[0] = new ECP2(); T[0].copy(Q[0]); // Q[0] |
| T[1] = new ECP2(); T[1].copy(T[0]); T[1].add(Q[1]); // Q[0]+Q[1] |
| T[2] = new ECP2(); T[2].copy(T[0]); T[2].add(Q[2]); // Q[0]+Q[2] |
| T[3] = new ECP2(); T[3].copy(T[1]); T[3].add(Q[2]); // Q[0]+Q[1]+Q[2] |
| T[4] = new ECP2(); T[4].copy(T[0]); T[4].add(Q[3]); // Q[0]+Q[3] |
| T[5] = new ECP2(); T[5].copy(T[1]); T[5].add(Q[3]); // Q[0]+Q[1]+Q[3] |
| T[6] = new ECP2(); T[6].copy(T[2]); T[6].add(Q[3]); // Q[0]+Q[2]+Q[3] |
| T[7] = new ECP2(); 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++) { |
| 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]=(byte)(2*t[0].parity()-1); |
| } |
| |
| // Recoded exponent |
| for (i=0; i<nb; i++) { |
| w[i]=0; |
| int k=1; |
| for (j=1; j<4; j++) { |
| byte bt=(byte)(s[i]*t[j].parity()); |
| t[j].fshr(1); |
| t[j].dec((int)(bt)>>1); |
| t[j].norm(); |
| w[i]+=bt*(byte)k; |
| k*=2; |
| } |
| } |
| |
| // Main loop |
| P.select(T,(int)(2*w[nb-1]+1)); |
| for (i=nb-2;i>=0;i--) { |
| P.dbl(); |
| W.select(T,(int)(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; |
| } |
| |
| |
| /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */ |
| /* |
| public static ECP2 mul4(ECP2[] Q,BIG[] u) |
| { |
| int i,j,nb; |
| int[] a=new int[4]; |
| ECP2 T=new ECP2(); |
| ECP2 C=new ECP2(); |
| ECP2 P=new ECP2(); |
| ECP2[] W=new ECP2[8]; |
| |
| BIG mt=new BIG(); |
| BIG[] t=new BIG[4]; |
| |
| byte[] w=new byte[BIG.NLEN*BIG.BASEBITS+1]; |
| |
| for (i=0;i<4;i++) |
| { |
| t[i]=new BIG(u[i]); |
| Q[i].affine(); |
| } |
| |
| // precompute table |
| |
| W[0]=new ECP2(); W[0].copy(Q[0]); W[0].sub(Q[1]); |
| |
| W[1]=new ECP2(); W[1].copy(W[0]); |
| W[2]=new ECP2(); W[2].copy(W[0]); |
| W[3]=new ECP2(); W[3].copy(W[0]); |
| W[4]=new ECP2(); W[4].copy(Q[0]); W[4].add(Q[1]); |
| W[5]=new ECP2(); W[5].copy(W[4]); |
| W[6]=new ECP2(); W[6].copy(W[4]); |
| W[7]=new ECP2(); 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]=(byte)(t[i].lastbits(2)-2); |
| t[i].dec(a[i]); t[i].norm(); |
| t[i].fshr(1); |
| } |
| w[j]=(byte)(8*a[0]+4*a[1]+2*a[2]+a[3]); |
| } |
| w[nb]=(byte)(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.select(W,w[i]); |
| P.dbl(); |
| P.add(T); |
| } |
| P.sub(C); // apply correction |
| |
| P.affine(); |
| return P; |
| } |
| */ |
| |
| /* needed for SOK */ |
| public static ECP2 mapit(byte[] h) |
| { |
| BIG q=new BIG(ROM.Modulus); |
| BIG x=BIG.fromBytes(h); |
| BIG one=new BIG(1); |
| FP2 X; |
| ECP2 Q; |
| x.mod(q); |
| while (true) |
| { |
| X=new FP2(one,x); |
| Q=new ECP2(X); |
| if (!Q.is_infinity()) break; |
| x.inc(1); x.norm(); |
| } |
| |
| BIG Fra=new BIG(ROM.Fra); |
| BIG Frb=new BIG(ROM.Frb); |
| X=new FP2(Fra,Frb); |
| |
| if (ECP.SEXTIC_TWIST==ECP.M_TYPE) |
| { |
| X.inverse(); |
| X.norm(); |
| } |
| |
| x=new BIG(ROM.CURVE_Bnx); |
| |
| /* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */ |
| |
| if (ECP.CURVE_PAIRING_TYPE==ECP.BN) |
| { |
| ECP2 T,K; |
| |
| T=new ECP2(); T.copy(Q); |
| T=T.mul(x); |
| |
| if (ECP.SIGN_OF_X==ECP.NEGATIVEX) |
| { |
| T.neg(); |
| } |
| K=new ECP2(); 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); |
| |
| } |
| |
| /* Efficient hash maps to G2 on BLS curves - Budroni, Pintore */ |
| /* Q -> x2Q -xQ -Q +F(xQ -Q) +F(F(2Q)) */ |
| |
| if (ECP.CURVE_PAIRING_TYPE==ECP.BLS) |
| { |
| // ECP2 xQ,x2Q; |
| // xQ=new ECP2(); |
| // x2Q=new ECP2(); |
| |
| ECP2 xQ=Q.mul(x); |
| ECP2 x2Q=xQ.mul(x); |
| |
| if (ECP.SIGN_OF_X==ECP.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; |
| } |
| |
| public static ECP2 generator() |
| { |
| return new ECP2(new FP2(new BIG(ROM.CURVE_Pxa),new BIG(ROM.CURVE_Pxb)),new FP2(new BIG(ROM.CURVE_Pya),new BIG(ROM.CURVE_Pyb))); |
| } |
| |
| /* |
| public static void main(String[] args) { |
| BIG r=new BIG(ROM.Modulus); |
| |
| BIG Pxa=new BIG(ROM.CURVE_Pxa); |
| BIG Pxb=new BIG(ROM.CURVE_Pxb); |
| BIG Pya=new BIG(ROM.CURVE_Pya); |
| BIG Pyb=new BIG(ROM.CURVE_Pyb); |
| |
| BIG Fra=new BIG(ROM.CURVE_Fra); |
| BIG Frb=new BIG(ROM.CURVE_Frb); |
| |
| FP2 f=new FP2(Fra,Frb); |
| |
| FP2 Px=new FP2(Pxa,Pxb); |
| FP2 Py=new FP2(Pya,Pyb); |
| |
| ECP2 P=new ECP2(Px,Py); |
| |
| System.out.println("P= "+P.toString()); |
| |
| P=P.mul(r); |
| System.out.println("P= "+P.toString()); |
| |
| ECP2 Q=new ECP2(Px,Py); |
| Q.frob(f); |
| System.out.println("Q= "+Q.toString()); |
| } */ |
| |
| |
| } |