/* return a^2 mod m */ public static BIG modsqr(BIG a, BIG m) { a.mod(m); DBIG d = sqr(a); return(d.mod(m)); }
/* return a*b mod m */ public static BIG modmul(BIG a, BIG b, BIG m) { a.mod(m); b.mod(m); DBIG d = mul(a, b); return(d.mod(m)); }
/* Generate Y = H(epoch, xCID/xID) */ public static void GET_Y(int TimeValue, sbyte[] xCID, sbyte[] Y) { sbyte[] h = hashit(TimeValue, xCID); BIG y = BIG.fromBytes(h); BIG q = new BIG(ROM.CURVE_Order); y.mod(q); y.toBytes(Y); }
/* 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); }
/* convert back to regular form */ public BIG redc() { if (ROM.MODTYPE != ROM.PSEUDO_MERSENNE) { DBIG d = new DBIG(x); return(BIG.mod(d)); } else { BIG r = new BIG(x); return(r); } }
/* this*=this mod Modulus */ public void sqr() { DBIG d; long ea = BIG.EXCESS(x); if ((ea + 1) * (ea + 1) + 1 >= ROM.FEXCESS) { reduce(); } d = BIG.sqr(x); x.copy(BIG.mod(d)); }
/* Jacobi Symbol (this/p). Returns 0, 1 or -1 */ public virtual int jacobi(BIG p) { int n8, k, m = 0; BIG t = new BIG(0); BIG x = new BIG(0); BIG n = new BIG(0); BIG zilch = new BIG(0); BIG one = new BIG(1); if (p.parity() == 0 || comp(this, zilch) == 0 || comp(p, one) <= 0) { return(0); } norm(); x.copy(this); n.copy(p); x.mod(p); while (comp(n, one) > 0) { if (comp(x, zilch) == 0) { return(0); } n8 = n.lastbits(3); k = 0; while (x.parity() == 0) { k++; x.shr(1); } if (k % 2 == 1) { m += (n8 * n8 - 1) / 8; } m += (n8 - 1) * (x.lastbits(2) - 1) / 4; t.copy(n); t.mod(x); n.copy(x); x.copy(t); m %= 2; } if (m == 0) { return(1); } else { return(-1); } }
/* this*=b mod Modulus */ public void mul(FP b) { long ea = BIG.EXCESS(x); long eb = BIG.EXCESS(b.x); if ((ea + 1) * (eb + 1) + 1 >= ROM.FEXCESS) { reduce(); } DBIG d = BIG.mul(x, b.x); x.copy(BIG.mod(d)); }
/* needed for SOK */ public static ECP2 mapit2(sbyte[] h) { BIG q = new BIG(ROM.Modulus); BIG x = BIG.fromBytes(h); BIG one = new BIG(1); FP2 X; ECP2 Q, T, K; x.mod(q); while (true) { X = new FP2(one, x); Q = new ECP2(X); if (!Q.is_infinity()) { break; } x.inc(1); x.norm(); } /* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */ BIG Fra = new BIG(ROM.CURVE_Fra); BIG Frb = new BIG(ROM.CURVE_Frb); X = new FP2(Fra, Frb); x = new BIG(ROM.CURVE_Bnx); T = new ECP2(); T.copy(Q); T.mul(x); T.neg(); K = new ECP2(); K.copy(T); K.dbl(); K.add(T); K.affine(); K.frob(X); Q.frob(X); Q.frob(X); Q.frob(X); Q.add(T); Q.add(K); T.frob(X); T.frob(X); Q.add(T); Q.affine(); return(Q); }
/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */ /* maps a random u to a point on the curve */ public static ECP map(BIG u, int cb) { ECP P; BIG x = new BIG(u); BIG p = new BIG(ROM.Modulus); x.mod(p); while (true) { P = new ECP(x, cb); if (!P.is_infinity()) { break; } x.inc(1); x.norm(); } return(P); }
public static ECP mapit(sbyte[] h) { BIG q = new BIG(ROM.Modulus); BIG x = BIG.fromBytes(h); x.mod(q); ECP P; while (true) { P = new ECP(x, 0); if (!P.is_infinity()) { break; } x.inc(1); x.norm(); } return(P); }
/* 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 -a mod m */ public static BIG modneg(BIG a, BIG m) { a.mod(m); return(m.minus(a)); }
/* reduce this mod Modulus */ public void reduce() { x.mod(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); }