/* this+=b */ public void add(FP b) { x.add(b.x); if (BIG.EXCESS(x) + 2 >= ROM.FEXCESS) { reduce(); } }
/* reduces this DBIG mod a DBIG in place */ /* public void mod(DBIG m) * { * int k=0; * if (comp(this,m)<0) return; * * do * { * m.shl(1); * k++; * } * while (comp(this,m)>=0); * * while (k>0) * { * m.shr(1); * if (comp(this,m)>=0) * { * sub(m); * norm(); * } * k--; * } * return; * * }*/ /* return this/c */ public virtual BIG div(BIG c) { int k = 0; DBIG m = new DBIG(c); 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); if (comp(this, m) > 0) { a.add(e); a.norm(); sub(m); norm(); } k--; } return(a); }
/* a=1/a mod 2^256. This is very fast! */ public virtual void invmod2m() { int i; BIG U = new BIG(0); BIG b = new BIG(0); BIG c = new BIG(0); U.inc(invmod256(lastbits(8))); for (i = 8; i < 256; i <<= 1) { b.copy(this); b.mod2m(i); BIG t1 = BIG.smul(U, b); t1.shr(i); c.copy(this); c.shr(i); c.mod2m(i); BIG t2 = BIG.smul(U, c); t2.mod2m(i); t1.add(t2); b = BIG.smul(t1, U); t1.copy(b); t1.mod2m(i); t2.one(); t2.shl(i); t1.rsub(t2); t1.norm(); t1.shl(i); U.add(t1); } this.copy(U); }
/* IEEE ECDSA Signature, C and D are signature on F using private key S */ public static int ECPSP_DSA(RAND RNG, sbyte[] S, sbyte[] F, sbyte[] C, sbyte[] D) { sbyte[] T = new sbyte[EFS]; BIG gx, gy, r, s, f, c, d, u, vx; ECP G, V; HASH H = new HASH(); H.process_array(F); sbyte[] B = H.hash(); gx = new BIG(ROM.CURVE_Gx); gy = new BIG(ROM.CURVE_Gy); G = new ECP(gx, gy); r = new BIG(ROM.CURVE_Order); s = BIG.fromBytes(S); f = BIG.fromBytes(B); c = new BIG(0); d = new BIG(0); V = new ECP(); do { u = BIG.randomnum(r, RNG); V.copy(G); V = V.mul(u); vx = V.X; c.copy(vx); c.mod(r); if (c.iszilch()) { continue; } u.invmodp(r); d.copy(BIG.modmul(s, c, r)); d.add(f); d.copy(BIG.modmul(u, d, r)); } while (d.iszilch()); c.toBytes(T); for (int i = 0; i < EFS; i++) { C[i] = T[i]; } d.toBytes(T); for (int i = 0; i < EFS; i++) { D[i] = T[i]; } return(0); }
/* Implement step 2 on client side of MPin protocol */ public static int CLIENT_2(sbyte[] X, sbyte[] Y, sbyte[] SEC) { BIG r = new BIG(ROM.CURVE_Order); ECP P = ECP.fromBytes(SEC); if (P.is_infinity()) { return(INVALID_POINT); } BIG px = BIG.fromBytes(X); BIG py = BIG.fromBytes(Y); px.add(py); px.mod(r); px.rsub(r); PAIR.G1mul(P, px).toBytes(SEC); return(0); }
/* Return e.this+f.Q */ public ECP mul2(BIG e, ECP Q, BIG f) { BIG te = new BIG(); BIG tf = new BIG(); BIG mt = new BIG(); ECP S = new ECP(); ECP T = new ECP(); ECP C = new ECP(); ECP[] W = new ECP[8]; sbyte[] w = new sbyte[1 + (ROM.NLEN * ROM.BASEBITS + 1) / 2]; int i, s, ns, nb; sbyte a, b; affine(); Q.affine(); te.copy(e); tf.copy(f); // precompute table W[1] = new ECP(); W[1].copy(this); W[1].sub(Q); W[2] = new ECP(); W[2].copy(this); W[2].add(Q); S.copy(Q); S.dbl(); W[0] = new ECP(); W[0].copy(W[1]); W[0].sub(S); W[3] = new ECP(); W[3].copy(W[2]); W[3].add(S); T.copy(this); T.dbl(); W[5] = new ECP(); W[5].copy(W[1]); W[5].add(T); W[6] = new ECP(); W[6].copy(W[2]); W[6].add(T); W[4] = new ECP(); W[4].copy(W[5]); W[4].sub(S); W[7] = new ECP(); W[7].copy(W[6]); W[7].add(S); // convert the table to affine if (ROM.CURVETYPE == ROM.WEIERSTRASS) { multiaffine(8, W); } // if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction s = te.parity(); te.inc(1); te.norm(); ns = te.parity(); mt.copy(te); mt.inc(1); mt.norm(); te.cmove(mt, s); T.cmove(this, ns); C.copy(T); s = tf.parity(); tf.inc(1); tf.norm(); ns = tf.parity(); mt.copy(tf); mt.inc(1); mt.norm(); tf.cmove(mt, s); S.cmove(Q, ns); C.add(S); mt.copy(te); mt.add(tf); mt.norm(); nb = 1 + (mt.nbits() + 1) / 2; // convert exponent to signed 2-bit window for (i = 0; i < nb; i++) { a = (sbyte)(te.lastbits(3) - 4); te.dec(a); te.norm(); te.fshr(2); b = (sbyte)(tf.lastbits(3) - 4); tf.dec(b); tf.norm(); tf.fshr(2); w[i] = (sbyte)(4 * a + b); } w[nb] = (sbyte)(4 * te.lastbits(3) + tf.lastbits(3)); S.copy(W[(w[nb] - 1) / 2]); for (i = nb - 1; i >= 0; i--) { T.select(W, w[i]); S.dbl(); S.dbl(); S.add(T); } S.sub(C); // apply correction S.affine(); return(S); }
/* reduce a DBIG to a BIG using the appropriate form of the modulus */ public static BIG mod(DBIG d) { BIG b; if (ROM.MODTYPE == ROM.PSEUDO_MERSENNE) { long v, tw; BIG t = d.Split(ROM.MODBITS); b = new BIG(d); unchecked { v = t.pmul((int)ROM.MConst); } tw = t.w[ROM.NLEN - 1]; t.w[ROM.NLEN - 1] &= ROM.TMASK; t.w[0] += (ROM.MConst * ((tw >> ROM.TBITS) + (v << (ROM.BASEBITS - ROM.TBITS)))); b.add(t); b.norm(); } if (ROM.MODTYPE == ROM.MONTGOMERY_FRIENDLY) { for (int i = 0; i < ROM.NLEN; i++) { d.w[ROM.NLEN + i] += d.muladd(d.w[i], ROM.MConst - 1, d.w[i], ROM.NLEN + i - 1); } b = new BIG(0); for (int i = 0; i < ROM.NLEN; i++) { b.w[i] = d.w[ROM.NLEN + i]; } b.norm(); } if (ROM.MODTYPE == ROM.NOT_SPECIAL) { BIG md = new BIG(ROM.Modulus); long m, carry; for (int i = 0; i < ROM.NLEN; i++) { if (ROM.MConst == -1) { m = (-d.w[i]) & ROM.MASK; } else { if (ROM.MConst == 1) { m = d.w[i]; } else { m = (ROM.MConst * d.w[i]) & ROM.MASK; } } carry = 0; for (int j = 0; j < ROM.NLEN; j++) { carry = d.muladd(m, md.w[j], carry, i + j); } d.w[ROM.NLEN + i] += carry; } b = new BIG(0); for (int i = 0; i < ROM.NLEN; i++) { b.w[i] = d.w[ROM.NLEN + i]; } b.norm(); } return(b); }
/* this=1/this mod p. Binary method */ public virtual void invmodp(BIG p) { mod(p); BIG u = new BIG(this); BIG v = new BIG(p); BIG x1 = new BIG(1); BIG x2 = new BIG(0); BIG t = new BIG(0); BIG one = new BIG(1); while (comp(u, one) != 0 && comp(v, one) != 0) { while (u.parity() == 0) { u.shr(1); if (x1.parity() != 0) { x1.add(p); x1.norm(); } x1.shr(1); } while (v.parity() == 0) { v.shr(1); if (x2.parity() != 0) { x2.add(p); x2.norm(); } x2.shr(1); } if (comp(u, v) >= 0) { u.sub(v); u.norm(); if (comp(x1, x2) >= 0) { x1.sub(x2); } else { t.copy(p); t.sub(x2); x1.add(t); } x1.norm(); } else { v.sub(u); v.norm(); if (comp(x2, x1) >= 0) { x2.sub(x1); } else { t.copy(p); t.sub(x1); x2.add(t); } x2.norm(); } } if (comp(u, one) == 0) { copy(x1); } else { copy(x2); } }
/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */ public static ECP2 mul4(ECP2[] Q, BIG[] u) { int i, j, nb; int[] a = new int[4]; ECP2 T = new ECP2(); ECP2 C = new ECP2(); ECP2 P = new ECP2(); ECP2[] W = new ECP2[8]; BIG mt = new BIG(); BIG[] t = new BIG[4]; sbyte[] w = new sbyte[ROM.NLEN * ROM.BASEBITS + 1]; for (i = 0; i < 4; i++) { t[i] = new BIG(u[i]); Q[i].affine(); } /* precompute table */ W[0] = new ECP2(); W[0].copy(Q[0]); W[0].sub(Q[1]); W[1] = new ECP2(); W[1].copy(W[0]); W[2] = new ECP2(); W[2].copy(W[0]); W[3] = new ECP2(); W[3].copy(W[0]); W[4] = new ECP2(); W[4].copy(Q[0]); W[4].add(Q[1]); W[5] = new ECP2(); W[5].copy(W[4]); W[6] = new ECP2(); W[6].copy(W[4]); W[7] = new ECP2(); W[7].copy(W[4]); T.copy(Q[2]); T.sub(Q[3]); W[1].sub(T); W[2].add(T); W[5].sub(T); W[6].add(T); T.copy(Q[2]); T.add(Q[3]); W[0].sub(T); W[3].add(T); W[4].sub(T); W[7].add(T); multiaffine(8, W); /* if multiplier is even add 1 to multiplier, and add P to correction */ mt.zero(); C.inf(); for (i = 0; i < 4; i++) { if (t[i].parity() == 0) { t[i].inc(1); t[i].norm(); C.add(Q[i]); } mt.add(t[i]); mt.norm(); } 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] = (sbyte)(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(W[(w[nb] - 1) / 2]); for (i = nb - 1; i >= 0; i--) { T.select(W, w[i]); P.dbl(); P.add(T); } P.sub(C); // apply correction P.affine(); return(P); }
/* 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); }