/* this=this^e */ /* Note this is simple square and multiply, so not side-channel safe */ public FP12 Pow(BIG e) { Norm(); e.Norm(); BIG e3 = new BIG(e); e3.PMul(3); e3.Norm(); FP12 w = new FP12(this); int nb = e3.NBits(); for (int i = nb - 2; i >= 1; i--) { w.USqr(); int bt = e3.Bit(i) - e.Bit(i); if (bt == 1) { w.mul(this); } if (bt == -1) { Conj(); w.mul(this); Conj(); } } w.Reduce(); return(w); /* * BIG z=new BIG(e); * FP12 r=new FP12(1); * * while (true) * { * int bt=z.parity(); * z.fshr(1); * if (bt==1) r.mul(w); * if (z.iszilch()) break; * w.usqr(); * } * r.reduce(); * 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); }
/* p=q0^u0.q1^u1.q2^u2.q3^u3 */ // 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 FP12 Pow4(FP12[] q, BIG[] u) { int i, j, nb, pb; FP12[] g = new FP12[8]; FP12 r = new FP12(1); FP12 p = new FP12(0); BIG[] t = new BIG[4]; BIG mt = new BIG(0); sbyte[] w = new sbyte[BIG.NLEN * BIG.BASEBITS + 1]; sbyte[] s = new sbyte[BIG.NLEN * BIG.BASEBITS + 1]; for (i = 0; i < 4; i++) { t[i] = new BIG(u[i]); t[i].Norm(); } g[0] = new FP12(q[0]); // q[0] g[1] = new FP12(g[0]); g[1].mul(q[1]); // q[0].q[1] g[2] = new FP12(g[0]); g[2].mul(q[2]); // q[0].q[2] g[3] = new FP12(g[1]); g[3].mul(q[2]); // q[0].q[1].q[2] g[4] = new FP12(q[0]); g[4].mul(q[3]); // q[0].q[3] g[5] = new FP12(g[1]); g[5].mul(q[3]); // q[0].q[1].q[3] g[6] = new FP12(g[2]); g[6].mul(q[3]); // q[0].q[2].q[3] g[7] = new FP12(g[3]); g[7].mul(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] = (sbyte)(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++) { sbyte bt = (sbyte)(s[i] * t[j].Parity()); t[j].FShr(1); t[j].Dec((int)(bt) >> 1); t[j].Norm(); w[i] += (sbyte)(bt * (sbyte)k); k *= 2; } } // Main loop p.Select(g, (int)(2 * w[nb - 1] + 1)); for (i = nb - 2; i >= 0; i--) { p.USqr(); r.Select(g, (int)(2 * w[i] + s[i])); p.mul(r); } // apply correction r.Copy(q[0]); r.Conj(); r.mul(p); p.CMove(r, pb); p.Reduce(); return(p); }