/* Galbraith & Scott Method */ public static BIG[] GS(BIG e) { BIG[] u = new BIG[4]; if (ECP.CURVE_PAIRING_TYPE == ECP.BN) { int i, j; BIG t = new BIG(0); BIG q = new BIG(ROM.CURVE_Order); BIG[] v = new BIG[4]; for (i = 0; i < 4; i++) { t.Copy(new BIG(ROM.CURVE_WB[i])); DBIG d = BIG.Mul(t, e); v[i] = new BIG(d.Div(q)); u[i] = new BIG(0); } u[0].Copy(e); for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { t.Copy(new BIG(ROM.CURVE_BB[j][i])); t.Copy(BIG.ModMul(v[j], t, q)); u[i].Add(q); u[i].Sub(t); u[i].Mod(q); } } } else { BIG q = new BIG(ROM.CURVE_Order); BIG x = new BIG(ROM.CURVE_Bnx); BIG w = new BIG(e); for (int i = 0; i < 3; i++) { u[i] = new BIG(w); u[i].Mod(x); w.Div(x); } u[3] = new BIG(w); if (ECP.SIGN_OF_X == ECP.NEGATIVEX) { u[1].Copy(BIG.ModNeg(u[1], q)); u[3].Copy(BIG.ModNeg(u[3], q)); } } return(u); }
/* convert to Montgomery n-residue form */ public void NRes() { if (MODTYPE != PSEUDO_MERSENNE && MODTYPE != GENERALISED_MERSENNE) { DBIG d = BIG.Mul(x, new BIG(ROM.R2modp)); //** Change ** x.Copy(Mod(d)); XES = 2; } else { XES = 1; } }
/* Multiply P by e in group G1 */ public static ECP G1Mul(ECP P, BIG e) { ECP R; if (USE_GLV) { //P.affine(); R = new ECP(); R.Copy(P); int np, nn; ECP Q = new ECP(); Q.Copy(P); Q.Affine(); BIG q = new BIG(ROM.CURVE_Order); FP cru = new FP(new BIG(ROM.CURVE_Cru)); BIG t = new BIG(0); BIG[] u = Glv(e); Q.GetX().Mul(cru); np = u[0].NBits(); t.Copy(BIG.ModNeg(u[0], q)); nn = t.NBits(); if (nn < np) { u[0].Copy(t); R.Neg(); } np = u[1].NBits(); t.Copy(BIG.ModNeg(u[1], q)); nn = t.NBits(); if (nn < np) { u[1].Copy(t); Q.Neg(); } u[0].Norm(); u[1].Norm(); R = R.Mul2(u[0], Q, u[1]); } else { R = P.Mul(e); } return(R); }
/* GLV method */ public static BIG[] Glv(BIG e) { BIG[] u = new BIG[2]; if (ECP.CURVE_PAIRING_TYPE == ECP.BN) { int i, j; BIG t = new BIG(0); BIG q = new BIG(ROM.CURVE_Order); BIG[] v = new BIG[2]; for (i = 0; i < 2; i++) { t.Copy(new BIG(ROM.CURVE_W[i])); // why not just t=new BIG(ROM.CURVE_W[i]); DBIG d = BIG.Mul(t, e); v[i] = new BIG(d.Div(q)); u[i] = new BIG(0); } u[0].Copy(e); for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { t.Copy(new BIG(ROM.CURVE_SB[j][i])); t.Copy(BIG.ModMul(v[j], t, q)); u[i].Add(q); u[i].Sub(t); u[i].Mod(q); } } } else { // -(x^2).P = (Beta.x,y) BIG q = new BIG(ROM.CURVE_Order); BIG x = new BIG(ROM.CURVE_Bnx); BIG x2 = BIG.SMul(x, x); u[0] = new BIG(e); u[0].Mod(x2); u[1] = new BIG(e); u[1].Div(x2); u[1].RSub(q); } return(u); }
/* 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); }
/* f=f^e */ /* Note that this method requires a lot of RAM! Better to use compressed XTR method, see FP4.java */ public static FP12 GTPow(FP12 d, BIG e) { FP12 r; if (USE_GS_GT) { FP12[] g = new FP12[4]; FP2 f = new FP2(new BIG(ROM.Fra), new BIG(ROM.Frb)); BIG q = new BIG(ROM.CURVE_Order); BIG t = new BIG(0); int i, np, nn; BIG[] u = GS(e); g[0] = new FP12(d); for (i = 1; i < 4; i++) { g[i] = new FP12(0); g[i].Copy(g[i - 1]); g[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); g[i].Conj(); } u[i].Norm(); } r = FP12.Pow4(g, u); } else { r = d.Pow(e); } return(r); }
/* return this/c */ public virtual BIG Div(BIG c) { int d, k = 0; DBIG m = new DBIG(c); DBIG dr = new DBIG(0); BIG r = new BIG(0); BIG a = new BIG(0); BIG e = new BIG(1); Norm(); while (Comp(this, m) >= 0) { e.FShl(1); m.Shl(1); k++; } while (k > 0) { m.Shr(1); e.Shr(1); dr.Copy(this); dr.Sub(m); dr.Norm(); d = (int)(1 - ((dr.w[BIG.DNLEN - 1] >> (BIG.CHUNK - 1)) & 1)); CMove(dr, d); r.Copy(a); r.Add(e); r.Norm(); a.CMove(r, d); k--; } return(a); }
/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */ public FP4 Xtr_Pow2(FP4 ck, FP4 ckml, FP4 ckm2l, BIG a, BIG b) { a.Norm(); b.Norm(); BIG e = new BIG(a); BIG d = new BIG(b); BIG w = new BIG(0); FP4 cu = new FP4(ck); // can probably be passed in w/o copying FP4 cv = new FP4(this); FP4 cumv = new FP4(ckml); FP4 cum2v = new FP4(ckm2l); FP4 r = new FP4(0); FP4 t = new FP4(0); int f2 = 0; while (d.Parity() == 0 && e.Parity() == 0) { d.FShr(1); e.FShr(1); f2++; } while (BIG.Comp(d, e) != 0) { if (BIG.Comp(d, e) > 0) { w.Copy(e); w.IMul(4); w.Norm(); if (BIG.Comp(d, w) <= 0) { w.Copy(d); d.Copy(e); e.RSub(w); e.Norm(); t.Copy(cv); t.Xtr_A(cu, cumv, cum2v); cum2v.Copy(cumv); cum2v.Conj(); cumv.Copy(cv); cv.Copy(cu); cu.Copy(t); } else if (d.Parity() == 0) { d.FShr(1); r.Copy(cum2v); r.Conj(); t.Copy(cumv); t.Xtr_A(cu, cv, r); cum2v.Copy(cumv); cum2v.Xtr_D(); cumv.Copy(t); cu.Xtr_D(); } else if (e.Parity() == 1) { d.Sub(e); d.Norm(); d.FShr(1); t.Copy(cv); t.Xtr_A(cu, cumv, cum2v); cu.Xtr_D(); cum2v.Copy(cv); cum2v.Xtr_D(); cum2v.Conj(); cv.Copy(t); } else { w.Copy(d); d.Copy(e); d.FShr(1); e.Copy(w); t.Copy(cumv); t.Xtr_D(); cumv.Copy(cum2v); cumv.Conj(); cum2v.Copy(t); cum2v.Conj(); t.Copy(cv); t.Xtr_D(); cv.Copy(cu); cu.Copy(t); } } if (BIG.Comp(d, e) < 0) { w.Copy(d); w.IMul(4); w.Norm(); if (BIG.Comp(e, w) <= 0) { e.Sub(d); e.Norm(); t.Copy(cv); t.Xtr_A(cu, cumv, cum2v); cum2v.Copy(cumv); cumv.Copy(cu); cu.Copy(t); } else if (e.Parity() == 0) { w.Copy(d); d.Copy(e); d.FShr(1); e.Copy(w); t.Copy(cumv); t.Xtr_D(); cumv.Copy(cum2v); cumv.Conj(); cum2v.Copy(t); cum2v.Conj(); t.Copy(cv); t.Xtr_D(); cv.Copy(cu); cu.Copy(t); } else if (d.Parity() == 1) { w.Copy(e); e.Copy(d); w.Sub(d); w.Norm(); d.Copy(w); d.FShr(1); t.Copy(cv); t.Xtr_A(cu, cumv, cum2v); cumv.Conj(); cum2v.Copy(cu); cum2v.Xtr_D(); cum2v.Conj(); cu.Copy(cv); cu.Xtr_D(); cv.Copy(t); } else { d.FShr(1); r.Copy(cum2v); r.Conj(); t.Copy(cumv); t.Xtr_A(cu, cv, r); cum2v.Copy(cumv); cum2v.Xtr_D(); cumv.Copy(t); cu.Xtr_D(); } } } r.Copy(cv); r.Xtr_A(cu, cumv, cum2v); for (int i = 0; i < f2; i++) { r.Xtr_D(); } r = r.Xtr_Pow(d); return(r); }
/* 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); }