/* Multiply P by e in group G2 */ public static ECP2 G2Mul(ECP2 P, BIG e) { ECP2 R; if (USE_GS_G2) { ECP2[] Q = new ECP2[4]; FP2 f = new FP2(new BIG(ROM.Fra), new BIG(ROM.Frb)); if (ECP.SEXTIC_TWIST == ECP.M_TYPE) { f.Inverse(); f.Norm(); } BIG q = new BIG(ROM.CURVE_Order); BIG[] u = GS(e); BIG t = new BIG(0); int i, np, nn; //P.affine(); Q[0] = new ECP2(); Q[0].Copy(P); for (i = 1; i < 4; i++) { Q[i] = new ECP2(); Q[i].Copy(Q[i - 1]); Q[i].Frob(f); } for (i = 0; i < 4; i++) { np = u[i].NBits(); t.Copy(BIG.ModNeg(u[i], q)); nn = t.NBits(); if (nn < np) { u[i].Copy(t); Q[i].Neg(); } u[i].Norm(); //Q[i].affine(); } R = ECP2.Mul4(Q, u); } else { R = P.Mul(e); } return(R); }
/* this=1/this */ public void Inverse() { // norm(); FP2 t1 = new FP2(a); FP2 t2 = new FP2(b); t1.Sqr(); t2.Sqr(); t2.Mul_Ip(); t2.Norm(); t1.Sub(t2); t1.Inverse(); a.Mul(t1); t1.Neg(); t1.Norm(); b.Mul(t1); }
/* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */ /* returns true if this is QR */ public bool Sqrt() { if (IsZilch()) { return(true); } FP2 wa = new FP2(a); FP2 ws = new FP2(b); FP2 wt = new FP2(a); if (ws.IsZilch()) { if (wt.Sqrt()) { a.Copy(wt); b.Zero(); } else { wt.Div_Ip(); wt.Sqrt(); b.Copy(wt); a.Zero(); } return(true); } ws.Sqr(); wa.Sqr(); ws.Mul_Ip(); ws.Norm(); wa.Sub(ws); ws.Copy(wa); if (!ws.Sqrt()) { return(false); } wa.Copy(wt); wa.Add(ws); wa.Norm(); wa.Div2(); if (!wa.Sqrt()) { wa.Copy(wt); wa.Sub(ws); wa.Norm(); wa.Div2(); if (!wa.Sqrt()) { return(false); } } wt.Copy(b); ws.Copy(wa); ws.Add(wa); ws.Inverse(); wt.Mul(ws); a.Copy(wa); b.Copy(wt); return(true); }
/* Optimal R-ate double pairing e(P,Q).e(R,S) */ public static FP12 Ate2(ECP2 P1, ECP Q1, ECP2 R1, ECP S1) { FP2 f; BIG x = new BIG(ROM.CURVE_Bnx); BIG n = new BIG(x); ECP2 K = new ECP2(); FP12 lv; int bt; ECP2 P = new ECP2(P1); ECP Q = new ECP(Q1); P.Affine(); Q.Affine(); ECP2 R = new ECP2(R1); ECP S = new ECP(S1); R.Affine(); S.Affine(); if (ECP.CURVE_PAIRING_TYPE == ECP.BN) { f = new FP2(new BIG(ROM.Fra), new BIG(ROM.Frb)); if (ECP.SEXTIC_TWIST == ECP.M_TYPE) { f.Inverse(); f.Norm(); } n.PMul(6); if (ECP.SIGN_OF_X == ECP.POSITIVEX) { n.Inc(2); } else { n.Dec(2); } } else { n.Copy(x); } n.Norm(); BIG n3 = new BIG(n); n3.PMul(3); n3.Norm(); FP Qx = new FP(Q.GetX()); FP Qy = new FP(Q.GetY()); FP Sx = new FP(S.GetX()); FP Sy = new FP(S.GetY()); ECP2 A = new ECP2(); ECP2 B = new ECP2(); FP12 r = new FP12(1); A.Copy(P); B.Copy(R); ECP2 MP = new ECP2(); MP.Copy(P); MP.Neg(); ECP2 MR = new ECP2(); MR.Copy(R); MR.Neg(); int nb = n3.NBits(); for (int i = nb - 2; i >= 1; i--) { r.Sqr(); lv = Line(A, A, Qx, Qy); r.SMul(lv, ECP.SEXTIC_TWIST); lv = Line(B, B, Sx, Sy); r.SMul(lv, ECP.SEXTIC_TWIST); bt = n3.Bit(i) - n.Bit(i); // bt=n.bit(i); if (bt == 1) { lv = Line(A, P, Qx, Qy); r.SMul(lv, ECP.SEXTIC_TWIST); lv = Line(B, R, Sx, Sy); r.SMul(lv, ECP.SEXTIC_TWIST); } if (bt == -1) { //P.neg(); lv = Line(A, MP, Qx, Qy); r.SMul(lv, ECP.SEXTIC_TWIST); //P.neg(); //R.neg(); lv = Line(B, MR, Sx, Sy); r.SMul(lv, ECP.SEXTIC_TWIST); //R.neg(); } } if (ECP.SIGN_OF_X == ECP.NEGATIVEX) { r.Conj(); } /* R-ate fixup required for BN curves */ if (ECP.CURVE_PAIRING_TYPE == ECP.BN) { if (ECP.SIGN_OF_X == ECP.NEGATIVEX) { // r.conj(); A.Neg(); B.Neg(); } K.Copy(P); K.Frob(f); lv = Line(A, K, Qx, Qy); r.SMul(lv, ECP.SEXTIC_TWIST); K.Frob(f); K.Neg(); lv = Line(A, K, Qx, Qy); r.SMul(lv, ECP.SEXTIC_TWIST); K.Copy(R); K.Frob(f); lv = Line(B, K, Sx, Sy); r.SMul(lv, ECP.SEXTIC_TWIST); K.Frob(f); K.Neg(); lv = Line(B, K, Sx, Sy); r.SMul(lv, ECP.SEXTIC_TWIST); } return(r); }