/* this/=2 mod Modulus */ public void Div2() { if (x.Parity() == 0) { x.FShr(1); } else { x.Add(new BIG(ROM.Modulus)); x.Norm(); x.FShr(1); } }
/* this=this^e */ public FP4 Pow(BIG e) { Norm(); e.Norm(); FP4 w = new FP4(this); BIG z = new BIG(e); FP4 r = new FP4(1); while (true) { int bt = z.Parity(); z.FShr(1); if (bt == 1) { r.Mul(w); } if (z.IsZilch()) { break; } w.Sqr(); } r.Reduce(); return(r); }
/* r=x^n using XTR method on traces of FP12s */ public FP4 Xtr_Pow(BIG n) { FP4 a = new FP4(3); FP4 b = new FP4(this); FP4 c = new FP4(b); c.Xtr_D(); FP4 t = new FP4(0); FP4 r = new FP4(0); n.Norm(); int par = n.Parity(); BIG v = new BIG(n); v.FShr(1); if (par == 0) { v.Dec(1); v.Norm(); } int nb = v.NBits(); for (int i = nb - 1; i >= 0; i--) { if (v.Bit(i) != 1) { t.Copy(b); Conj(); c.Conj(); b.Xtr_A(a, this, c); Conj(); c.Copy(t); c.Xtr_D(); a.Xtr_D(); } else { t.Copy(a); t.Conj(); a.Copy(b); a.Xtr_D(); b.Xtr_A(c, this, t); c.Xtr_D(); } } if (par == 0) { r.Copy(c); } else { r.Copy(b); } r.Reduce(); return(r); }
public FP Pow(BIG e) { sbyte[] w = new sbyte[1 + (BIG.NLEN * BIG.BASEBITS + 3) / 4]; FP[] tb = new FP[16]; BIG t = new BIG(e); t.Norm(); int nb = 1 + (t.NBits() + 3) / 4; for (int i = 0; i < nb; i++) { int lsbs = t.LastBits(4); t.Dec(lsbs); t.Norm(); w[i] = (sbyte)lsbs; t.FShr(4); } tb[0] = new FP(1); tb[1] = new FP(this); for (int i = 2; i < 16; i++) { tb[i] = new FP(tb[i - 1]); tb[i].Mul(this); } FP r = new FP(tb[w[nb - 1]]); for (int i = nb - 2; i >= 0; i--) { r.Sqr(); r.Sqr(); r.Sqr(); r.Sqr(); r.Mul(tb[w[i]]); } r.Reduce(); return(r); }
/* 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); }
/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */ public static FP12 FExp(FP12 m) { FP2 f = new FP2(new BIG(ROM.Fra), new BIG(ROM.Frb)); BIG x = new BIG(ROM.CURVE_Bnx); FP12 r = new FP12(m); /* Easy part of final exp */ FP12 lv = new FP12(r); lv.Inverse(); r.Conj(); r.mul(lv); lv.Copy(r); r.Frob(f); r.Frob(f); r.mul(lv); /* Hard part of final exp */ if (ECP.CURVE_PAIRING_TYPE == ECP.BN) { FP12 x0, x1, x2, x3, x4, x5; lv.Copy(r); lv.Frob(f); x0 = new FP12(lv); x0.Frob(f); lv.mul(r); x0.mul(lv); x0.Frob(f); x1 = new FP12(r); x1.Conj(); x4 = r.Pow(x); if (ECP.SIGN_OF_X == ECP.POSITIVEX) { x4.Conj(); } x3 = new FP12(x4); x3.Frob(f); x2 = x4.Pow(x); if (ECP.SIGN_OF_X == ECP.POSITIVEX) { x2.Conj(); } x5 = new FP12(x2); x5.Conj(); lv = x2.Pow(x); if (ECP.SIGN_OF_X == ECP.POSITIVEX) { lv.Conj(); } x2.Frob(f); r.Copy(x2); r.Conj(); x4.mul(r); x2.Frob(f); r.Copy(lv); r.Frob(f); lv.mul(r); lv.USqr(); lv.mul(x4); lv.mul(x5); r.Copy(x3); r.mul(x5); r.mul(lv); lv.mul(x2); r.USqr(); r.mul(lv); r.USqr(); lv.Copy(r); lv.mul(x1); r.mul(x0); lv.USqr(); r.mul(lv); r.Reduce(); } else { FP12 y0, y1, y2, y3; // Ghamman & Fouotsa Method y0 = new FP12(r); y0.USqr(); y1 = y0.Pow(x); if (ECP.SIGN_OF_X == ECP.NEGATIVEX) { y1.Conj(); } x.FShr(1); y2 = y1.Pow(x); if (ECP.SIGN_OF_X == ECP.NEGATIVEX) { y2.Conj(); } x.FShl(1); y3 = new FP12(r); y3.Conj(); y1.mul(y3); y1.Conj(); y1.mul(y2); y2 = y1.Pow(x); if (ECP.SIGN_OF_X == ECP.NEGATIVEX) { y2.Conj(); } y3 = y2.Pow(x); if (ECP.SIGN_OF_X == ECP.NEGATIVEX) { y3.Conj(); } y1.Conj(); y3.mul(y1); y1.Conj(); y1.Frob(f); y1.Frob(f); y1.Frob(f); y2.Frob(f); y2.Frob(f); y1.mul(y2); y2 = y3.Pow(x); if (ECP.SIGN_OF_X == ECP.NEGATIVEX) { y2.Conj(); } y2.mul(y0); y2.mul(r); y1.mul(y2); y2.Copy(y3); y2.Frob(f); y1.mul(y2); r.Copy(y1); r.Reduce(); } return(r); }