/* 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); }