/* this=this^e */ public FP12 pow(BIG e) { norm(); e.norm(); FP12 w = new FP12(this); 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); }
/* Pollards kangaroos used to return PIN error */ public static int KANGAROO(sbyte[] E, sbyte[] F) { FP12 ge = FP12.fromBytes(E); FP12 gf = FP12.fromBytes(F); int[] distance = new int[TS]; FP12 t = new FP12(gf); FP12[] table = new FP12[TS]; int i, j, m, s, dn, dm, res, steps; s = 1; for (m = 0; m < TS; m++) { distance[m] = s; table[m] = new FP12(t); s *= 2; t.usqr(); } t.one(); dn = 0; for (j = 0; j < TRAP; j++) { i = t.geta().geta().A.lastbits(8) % TS; t.mul(table[i]); dn += distance[i]; } gf.copy(t); gf.conj(); steps = 0; dm = 0; res = 0; while (dm - dn < MAXPIN) { steps++; if (steps > 4 * TRAP) { break; } i = ge.geta().geta().A.lastbits(8) % TS; ge.mul(table[i]); dm += distance[i]; if (ge.Equals(t)) { res = dm - dn; break; } if (ge.Equals(gf)) { res = dn - dm; break; } } if (steps > 4 * TRAP || dm - dn >= MAXPIN) { res = 0; } // Trap Failed - probable invalid token return(res); }
/* Optimal R-ate pairing */ public static FP12 ate(ECP2 P, ECP Q) { FP2 f = new FP2(new BIG(ROM.CURVE_Fra), new BIG(ROM.CURVE_Frb)); BIG x = new BIG(ROM.CURVE_Bnx); BIG n = new BIG(x); ECP2 K = new ECP2(); FP12 lv; n.pmul(6); n.dec(2); n.norm(); P.affine(); Q.affine(); FP Qx = new FP(Q.getx()); FP Qy = new FP(Q.gety()); ECP2 A = new ECP2(); FP12 r = new FP12(1); A.copy(P); int nb = n.nbits(); for (int i = nb - 2; i >= 1; i--) { lv = line(A, A, Qx, Qy); r.smul(lv); if (n.bit(i) == 1) { lv = line(A, P, Qx, Qy); r.smul(lv); } r.sqr(); } lv = line(A, A, Qx, Qy); r.smul(lv); /* R-ate fixup */ r.conj(); K.copy(P); K.frob(f); A.neg(); lv = line(A, K, Qx, Qy); r.smul(lv); K.frob(f); K.neg(); lv = line(A, K, Qx, Qy); r.smul(lv); return(r); }
/* constant time powering by small integer of max length bts */ public void pinpow(int e, int bts) { int i, b; FP12[] R = new FP12[2]; R[0] = new FP12(1); R[1] = new FP12(this); for (i = bts - 1; i >= 0; i--) { b = (e >> i) & 1; R[1 - b].mul(R[b]); R[b].usqr(); } this.copy(R[0]); }
/* 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; */ }
/* 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); }
/* test group membership */ /* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */ public static bool GTmember(FP12 m) { if (m.isunity()) { return(false); } FP12 r = new FP12(m); r.conj(); r.mul(m); if (!r.isunity()) { return(false); } FP2 f = new FP2(new BIG(ROM.CURVE_Fra), new BIG(ROM.CURVE_Frb)); r.copy(m); r.frob(f); r.frob(f); FP12 w = new FP12(r); w.frob(f); w.frob(f); w.mul(m); if (!ROM.GT_STRONG) { if (!w.Equals(r)) { return(false); } BIG x = new BIG(ROM.CURVE_Bnx); r.copy(m); w = r.pow(x); w = w.pow(x); r.copy(w); r.sqr(); r.mul(w); r.sqr(); w.copy(m); w.frob(f); } return(w.Equals(r)); }
public FP4 ComPow(BIG e, BIG r) { FP12 g1 = new FP12(0); FP12 g2 = new FP12(0); FP2 f = new FP2(new BIG(ROM.Fra), new BIG(ROM.Frb)); BIG q = new BIG(ROM.Modulus); BIG m = new BIG(q); m.Mod(r); BIG a = new BIG(e); a.Mod(m); BIG b = new BIG(e); b.Div(m); g1.Copy(this); g2.Copy(this); FP4 c = g1.Trace(); if (b.IsZilch()) { c = c.Xtr_Pow(e); return(c); } g2.Frob(f); FP4 cp = g2.Trace(); g1.Conj(); g2.mul(g1); FP4 cpm1 = g2.Trace(); g2.mul(g1); FP4 cpm2 = g2.Trace(); c = c.Xtr_Pow2(cp, cpm1, cpm2, a, b); return(c); }
/* Special case of multiplication arises from special form of ATE pairing line function */ public void smul(FP12 y) { FP4 z0 = new FP4(a); FP4 z2 = new FP4(b); FP4 z3 = new FP4(b); FP4 t0 = new FP4(0); FP4 t1 = new FP4(y.a); z0.mul(y.a); z2.pmul(y.b.real()); b.add(a); t1.real().add(y.b.real()); b.mul(t1); z3.add(c); z3.pmul(y.b.real()); t0.copy(z0); t0.neg(); t1.copy(z2); t1.neg(); b.add(t0); // b.norm(); b.add(t1); z3.add(t1); z2.add(t0); t0.copy(a); t0.add(c); t0.mul(y.a); c.copy(z2); c.add(t0); z3.times_i(); a.copy(z0); a.add(z3); norm(); }
/* Constant time select from pre-computed table */ public void Select(FP12[] g, int b) { int m = b >> 31; int babs = (b ^ m) - m; babs = (babs - 1) / 2; CMove(g[0], Teq(babs, 0)); // conditional move CMove(g[1], Teq(babs, 1)); CMove(g[2], Teq(babs, 2)); CMove(g[3], Teq(babs, 3)); CMove(g[4], Teq(babs, 4)); CMove(g[5], Teq(babs, 5)); CMove(g[6], Teq(babs, 6)); CMove(g[7], Teq(babs, 7)); FP12 invf = new FP12(this); invf.Conj(); CMove(invf, (int)(m & 1)); }
/* 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 (ROM.USE_GS_GT) { FP12[] g = new FP12[4]; FP2 f = new FP2(new BIG(ROM.CURVE_Fra), new BIG(ROM.CURVE_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(); } } r = FP12.pow4(g, u); } else { r = d.pow(e); } return(r); }
/* p=q0^u0.q1^u1.q2^u2.q3^u3 */ /* Timing attack secure, but not cache attack secure */ public static FP12 pow4(FP12[] q, BIG[] u) { int i, j, nb, m; int[] a = new int[4]; FP12[] g = new FP12[8]; FP12[] s = new FP12[2]; FP12 c = new FP12(1); FP12 p = new FP12(0); BIG[] t = new BIG[4]; BIG mt = new BIG(0); sbyte[] w = new sbyte[ROM.NLEN * ROM.BASEBITS + 1]; for (i = 0; i < 4; i++) { t[i] = new BIG(u[i]); } s[0] = new FP12(0); s[1] = new FP12(0); g[0] = new FP12(q[0]); s[0].copy(q[1]); s[0].conj(); g[0].mul(s[0]); g[1] = new FP12(g[0]); g[2] = new FP12(g[0]); g[3] = new FP12(g[0]); g[4] = new FP12(q[0]); g[4].mul(q[1]); g[5] = new FP12(g[4]); g[6] = new FP12(g[4]); g[7] = new FP12(g[4]); s[1].copy(q[2]); s[0].copy(q[3]); s[0].conj(); s[1].mul(s[0]); s[0].copy(s[1]); s[0].conj(); g[1].mul(s[0]); g[2].mul(s[1]); g[5].mul(s[0]); g[6].mul(s[1]); s[1].copy(q[2]); s[1].mul(q[3]); s[0].copy(s[1]); s[0].conj(); g[0].mul(s[0]); g[3].mul(s[1]); g[4].mul(s[0]); g[7].mul(s[1]); /* if power is even add 1 to power, and add q to correction */ for (i = 0; i < 4; i++) { if (t[i].parity() == 0) { t[i].inc(1); t[i].norm(); c.mul(q[i]); } mt.add(t[i]); mt.norm(); } c.conj(); nb = 1 + mt.nbits(); /* convert exponent to signed 1-bit window */ for (j = 0; j < nb; j++) { for (i = 0; i < 4; i++) { a[i] = (t[i].lastbits(2) - 2); t[i].dec(a[i]); t[i].norm(); t[i].fshr(1); } w[j] = (sbyte)(8 * a[0] + 4 * a[1] + 2 * a[2] + a[3]); } w[nb] = (sbyte)(8 * t[0].lastbits(2) + 4 * t[1].lastbits(2) + 2 * t[2].lastbits(2) + t[3].lastbits(2)); p.copy(g[(w[nb] - 1) / 2]); for (i = nb - 1; i >= 0; i--) { m = w[i] >> 7; j = (w[i] ^ m) - m; // j=abs(w[i]) j = (j - 1) / 2; s[0].copy(g[j]); s[1].copy(g[j]); s[1].conj(); p.usqr(); p.mul(s[m & 1]); } p.mul(c); // apply correction p.reduce(); return(p); }
/* calculate common key on client side */ /* wCID = w.(A+AT) */ public static int CLIENT_KEY(sbyte[] G1, sbyte[] G2, int pin, sbyte[] R, sbyte[] X, sbyte[] wCID, sbyte[] CK) { HASH H = new HASH(); sbyte[] t = new sbyte[EFS]; FP12 g1 = FP12.fromBytes(G1); FP12 g2 = FP12.fromBytes(G2); BIG z = BIG.fromBytes(R); BIG x = BIG.fromBytes(X); ECP W = ECP.fromBytes(wCID); if (W.is_infinity()) { return(INVALID_POINT); } W = PAIR.G1mul(W, x); FP2 f = new FP2(new BIG(ROM.CURVE_Fra), new BIG(ROM.CURVE_Frb)); BIG r = new BIG(ROM.CURVE_Order); BIG q = new BIG(ROM.Modulus); BIG m = new BIG(q); m.mod(r); BIG a = new BIG(z); a.mod(m); BIG b = new BIG(z); b.div(m); g2.pinpow(pin, PBLEN); g1.mul(g2); FP4 c = g1.trace(); g2.copy(g1); g2.frob(f); FP4 cp = g2.trace(); g1.conj(); g2.mul(g1); FP4 cpm1 = g2.trace(); g2.mul(g1); FP4 cpm2 = g2.trace(); c = c.xtr_pow2(cp, cpm1, cpm2, a, b); c.geta().A.toBytes(t); H.process_array(t); c.geta().B.toBytes(t); H.process_array(t); c.getb().A.toBytes(t); H.process_array(t); c.getb().B.toBytes(t); H.process_array(t); W.X.toBytes(t); H.process_array(t); W.Y.toBytes(t); H.process_array(t); t = H.hash(); for (int i = 0; i < PAS; i++) { CK[i] = t[i]; } return(0); }
/* return 1 if x==y, else 0 */ public bool Equals(FP12 x) { return(a.Equals(x.a) && b.Equals(x.b) && c.Equals(x.c)); }
/* calculate common key on server side */ /* Z=r.A - no time permits involved */ public static int SERVER_KEY(sbyte[] Z, sbyte[] SST, sbyte[] W, sbyte[] xID, sbyte[] xCID, sbyte[] SK) { HASH H = new HASH(); sbyte[] t = new sbyte[EFS]; ECP2 sQ = ECP2.fromBytes(SST); if (sQ.is_infinity()) { return(INVALID_POINT); } ECP R = ECP.fromBytes(Z); if (R.is_infinity()) { return(INVALID_POINT); } ECP U; if (xCID != null) { U = ECP.fromBytes(xCID); } else { U = ECP.fromBytes(xID); } if (U.is_infinity()) { return(INVALID_POINT); } BIG w = BIG.fromBytes(W); U = PAIR.G1mul(U, w); FP12 g = PAIR.ate(sQ, R); g = PAIR.fexp(g); FP4 c = g.trace(); c.geta().A.toBytes(t); H.process_array(t); c.geta().B.toBytes(t); H.process_array(t); c.getb().A.toBytes(t); H.process_array(t); c.getb().B.toBytes(t); H.process_array(t); U.X.toBytes(t); H.process_array(t); U.Y.toBytes(t); H.process_array(t); t = H.hash(); for (int i = 0; i < PAS; i++) { SK[i] = t[i]; } return(0); }
/* copy this=x */ public void Copy(FP12 x) { a.Copy(x.a); b.Copy(x.b); c.Copy(x.c); }
/* FP12 full multiplication this=this*y */ public void mul(FP12 y) { FP4 z0 = new FP4(a); FP4 z1 = new FP4(0); FP4 z2 = new FP4(b); FP4 z3 = new FP4(0); FP4 t0 = new FP4(a); FP4 t1 = new FP4(y.a); z0.mul(y.a); z2.mul(y.b); t0.add(b); t1.add(y.b); z1.copy(t0); z1.mul(t1); t0.copy(b); t0.add(c); t1.copy(y.b); t1.add(y.c); z3.copy(t0); z3.mul(t1); t0.copy(z0); t0.neg(); t1.copy(z2); t1.neg(); z1.add(t0); // z1.norm(); b.copy(z1); b.add(t1); z3.add(t1); z2.add(t0); t0.copy(a); t0.add(c); t1.copy(y.a); t1.add(y.c); t0.mul(t1); z2.add(t0); t0.copy(c); t0.mul(y.c); t1.copy(t0); t1.neg(); // z2.norm(); // z3.norm(); // b.norm(); c.copy(z2); c.add(t1); z3.add(t1); t0.times_i(); b.add(t0); z3.times_i(); a.copy(z0); a.add(z3); norm(); }
public FP12(FP12 x) { a = new FP4(x.a); b = new FP4(x.b); c = new FP4(x.c); }
/* FP12 full multiplication this=this*y */ public void mul(FP12 y) { //System.out.println("Into mul"); FP4 z0 = new FP4(a); FP4 z1 = new FP4(0); FP4 z2 = new FP4(b); FP4 z3 = new FP4(0); FP4 t0 = new FP4(a); FP4 t1 = new FP4(y.a); z0.Mul(y.a); z2.Mul(y.b); t0.Add(b); t1.Add(y.b); t0.Norm(); t1.Norm(); z1.Copy(t0); z1.Mul(t1); t0.Copy(b); t0.Add(c); t1.Copy(y.b); t1.Add(y.c); t0.Norm(); t1.Norm(); z3.Copy(t0); z3.Mul(t1); t0.Copy(z0); t0.Neg(); t1.Copy(z2); t1.Neg(); z1.Add(t0); //z1.norm(); b.Copy(z1); b.Add(t1); z3.Add(t1); z2.Add(t0); t0.Copy(a); t0.Add(c); t1.Copy(y.a); t1.Add(y.c); t0.Norm(); t1.Norm(); t0.Mul(t1); z2.Add(t0); t0.Copy(c); t0.Mul(y.c); t1.Copy(t0); t1.Neg(); // z2.norm(); // z3.norm(); // b.norm(); c.Copy(z2); c.Add(t1); z3.Add(t1); t0.Times_I(); b.Add(t0); z3.Norm(); z3.Times_I(); a.Copy(z0); a.Add(z3); Norm(); //System.out.println("Out of mul"); }
/* 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); }
/* 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); }
/* 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); }
/* copy this=x */ public void copy(FP12 x) { a.copy(x.a); b.copy(x.b); c.copy(x.c); }
/* Special case of multiplication arises from special form of ATE pairing line function */ public void SMul(FP12 y, int type) { //System.out.println("Into smul"); if (type == ECP.D_TYPE) { FP4 z0 = new FP4(a); FP4 z2 = new FP4(b); FP4 z3 = new FP4(b); FP4 t0 = new FP4(0); FP4 t1 = new FP4(y.a); z0.Mul(y.a); z2.PMul(y.b.Real()); b.Add(a); t1.Real().Add(y.b.Real()); t1.Norm(); b.Norm(); b.Mul(t1); z3.Add(c); z3.Norm(); z3.PMul(y.b.Real()); t0.Copy(z0); t0.Neg(); t1.Copy(z2); t1.Neg(); b.Add(t0); b.Add(t1); z3.Add(t1); z2.Add(t0); t0.Copy(a); t0.Add(c); t0.Norm(); z3.Norm(); t0.Mul(y.a); c.Copy(z2); c.Add(t0); z3.Times_I(); a.Copy(z0); a.Add(z3); } if (type == ECP.M_TYPE) { FP4 z0 = new FP4(a); FP4 z1 = new FP4(0); FP4 z2 = new FP4(0); FP4 z3 = new FP4(0); FP4 t0 = new FP4(a); FP4 t1 = new FP4(0); z0.Mul(y.a); t0.Add(b); t0.Norm(); z1.Copy(t0); z1.Mul(y.a); t0.Copy(b); t0.Add(c); t0.Norm(); z3.Copy(t0); //z3.mul(y.c); z3.PMul(y.c.GetB()); z3.Times_I(); t0.Copy(z0); t0.Neg(); z1.Add(t0); b.Copy(z1); z2.Copy(t0); t0.Copy(a); t0.Add(c); t1.Copy(y.a); t1.Add(y.c); t0.Norm(); t1.Norm(); t0.Mul(t1); z2.Add(t0); t0.Copy(c); t0.PMul(y.c.GetB()); t0.Times_I(); t1.Copy(t0); t1.Neg(); c.Copy(z2); c.Add(t1); z3.Add(t1); t0.Times_I(); b.Add(t0); z3.Norm(); z3.Times_I(); a.Copy(z0); a.Add(z3); } Norm(); //System.out.println("Out of smul"); }
public void CMove(FP12 g, int d) { a.CMove(g.a, d); b.CMove(g.b, d); c.CMove(g.c, d); }
/** * Verify this signature * * @param disclosure an array indicating which attributes it expects to be disclosed * @param ipk the issuer public key * @param msg the message that should be signed in this signature * @param attributeValues BIG array where attributeValues[i] contains the desired attribute value for the i-th attribute if its disclosed * @param rhIndex index of the attribute that represents the revocation-handle * @param revPk the long term public key used to authenticate CRIs * @param epoch monotonically increasing counter representing a time window * @return true iff valid */ // ReSharper disable once ParameterHidesMember public bool Verify(bool[] disclosure, IdemixIssuerPublicKey ipk, byte[] msg, BIG[] attributeValues, int rhIndex, KeyPair revPk, int epoch) { if (disclosure == null || ipk == null || msg == null || attributeValues == null || attributeValues.Length != ipk.AttributeNames.Length || disclosure.Length != ipk.AttributeNames.Length) { return(false); } for (int i = 0; i < ipk.AttributeNames.Length; i++) { if (disclosure[i] && attributeValues[i] == null) { return(false); } } int[] hiddenIndices = HiddenIndices(disclosure); if (proofSAttrs.Length != hiddenIndices.Length) { return(false); } if (aPrime.IsInfinity()) { return(false); } if (nonRevocationProof.RevocationAlg >= Enum.GetValues(typeof(RevocationAlgorithm)).Length) { throw new ArgumentException("CRI specifies unknown revocation algorithm"); } RevocationAlgorithm revocationAlgorithm = (RevocationAlgorithm)nonRevocationProof.RevocationAlg; if (disclosure[rhIndex]) { throw new ArgumentException("Attribute " + rhIndex + " is disclosed but also used a revocation handle attribute, which should remain hidden"); } // Verify EpochPK if (!RevocationAuthority.VerifyEpochPK(revPk, revocationPk, revocationPKSig, epoch, revocationAlgorithm)) { // Signature is based on an invalid revocation epoch public key return(false); } FP12 temp1 = PAIR.Ate(ipk.W, aPrime); FP12 temp2 = PAIR.Ate(IdemixUtils.GenG2, aBar); temp2.Inverse(); temp1.mul(temp2); if (!PAIR.FExp(temp1).IsUnity()) { return(false); } ECP t1 = aPrime.Mul2(proofSE, ipk.HRand, proofSR2); ECP temp = new ECP(); temp.Copy(aBar); temp.Sub(bPrime); t1.Sub(PAIR.G1Mul(temp, proofC)); ECP t2 = PAIR.G1Mul(ipk.HRand, proofSSPrime); t2.Add(bPrime.Mul2(proofSR3, ipk.Hsk, proofSSk)); for (int i = 0; i < hiddenIndices.Length / 2; i++) { t2.Add(ipk.HAttrs[hiddenIndices[2 * i]].Mul2(proofSAttrs[2 * i], ipk.HAttrs[hiddenIndices[2 * i + 1]], proofSAttrs[2 * i + 1])); } if (hiddenIndices.Length % 2 != 0) { t2.Add(PAIR.G1Mul(ipk.HAttrs[hiddenIndices[hiddenIndices.Length - 1]], proofSAttrs[hiddenIndices.Length - 1])); } temp = new ECP(); temp.Copy(IdemixUtils.GenG1); for (int i = 0; i < disclosure.Length; i++) { if (disclosure[i]) { temp.Add(PAIR.G1Mul(ipk.HAttrs[i], attributeValues[i])); } } t2.Add(PAIR.G1Mul(temp, proofC)); ECP t3 = ipk.Hsk.Mul2(proofSSk, ipk.HRand, proofSRNym); t3.Sub(nym.Mul(proofC)); // Check with non-revoked-verifier INonRevocationVerifier nonRevokedVerifier = NonRevocationVerifier.GetNonRevocationVerifier(revocationAlgorithm); int hiddenRHIndex = Array.IndexOf(hiddenIndices, rhIndex); if (hiddenRHIndex < 0) { // rhIndex is not present, set to last index position hiddenRHIndex = hiddenIndices.Length; } BIG proofSRh = proofSAttrs[hiddenRHIndex]; byte[] nonRevokedProofBytes = nonRevokedVerifier.RecomputeFSContribution(nonRevocationProof, proofC, revocationPk.ToECP2(), proofSRh); if (nonRevokedProofBytes == null) { return(false); } // create proofData such that it can contain the sign label, 7 elements in G1 (each of size 2*FIELD_BYTES+1), // the ipk hash, the disclosure array, and the message byte[] proofData = new byte[0]; proofData = proofData.Append(SIGN_LABEL.ToBytes()); proofData = proofData.Append(t1.ToBytes()); proofData = proofData.Append(t2.ToBytes()); proofData = proofData.Append(t3.ToBytes()); proofData = proofData.Append(aPrime.ToBytes()); proofData = proofData.Append(aBar.ToBytes()); proofData = proofData.Append(bPrime.ToBytes()); proofData = proofData.Append(nym.ToBytes()); proofData = proofData.Append(ipk.Hash); proofData = proofData.Append(disclosure); proofData = proofData.Append(msg); BIG cvalue = proofData.HashModOrder(); byte[] finalProofData = new byte[0]; finalProofData = finalProofData.Append(cvalue.ToBytes()); finalProofData = finalProofData.Append(nonce.ToBytes()); byte[] hashedProofData = finalProofData.HashModOrder().ToBytes(); return(Enumerable.SequenceEqual(proofC.ToBytes(), hashedProofData)); }
/* 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.CURVE_Fra), new BIG(ROM.CURVE_Frb)); BIG x = new BIG(ROM.CURVE_Bnx); FP12 r = new FP12(m); FP12 x0, x1, x2, x3, x4, x5; /* 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 */ 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); x3 = new FP12(x4); x3.frob(f); x2 = x4.pow(x); x5 = new FP12(x2); x5.conj(); lv = x2.pow(x); 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(); return(r); }