/* return this^e mod m */ public virtual BIG powmod(BIG e, BIG m) { int bt; norm(); e.norm(); BIG a = new BIG(1); BIG z = new BIG(e); BIG s = new BIG(this); while (true) { bt = z.parity(); z.fshr(1); if (bt == 1) { a = modmul(a, s, m); } if (z.iszilch()) { break; } s = modsqr(s, m); } return(a); }
/* 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); }
/* return this^e mod Modulus */ public FP pow(BIG e) { int bt; FP r = new FP(1); e.norm(); x.norm(); FP m = new FP(this); while (true) { bt = e.parity(); e.fshr(1); if (bt == 1) { r.mul(m); } if (e.iszilch()) { break; } m.sqr(); } r.x.mod(p); return(r); }
/* 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); }
/* return e.this */ public ECP mul(BIG e) { if (e.iszilch() || is_infinity()) { return(new ECP()); } ECP P = new ECP(); if (ROM.CURVETYPE == ROM.MONTGOMERY) { /* use Ladder */ int nb, i, b; ECP D = new ECP(); ECP R0 = new ECP(); R0.copy(this); ECP R1 = new ECP(); R1.copy(this); R1.dbl(); D.copy(this); D.affine(); nb = e.nbits(); for (i = nb - 2; i >= 0; i--) { b = e.bit(i); P.copy(R1); P.dadd(R0, D); R0.cswap(R1, b); R1.copy(P); R0.dbl(); R0.cswap(R1, b); } P.copy(R0); } else { // fixed size windows int i, b, nb, m, s, ns; BIG mt = new BIG(); BIG t = new BIG(); ECP Q = new ECP(); ECP C = new ECP(); ECP[] W = new ECP[8]; sbyte[] w = new sbyte[1 + (ROM.NLEN * ROM.BASEBITS + 3) / 4]; affine(); // precompute table Q.copy(this); Q.dbl(); W[0] = new ECP(); W[0].copy(this); for (i = 1; i < 8; i++) { W[i] = new ECP(); W[i].copy(W[i - 1]); W[i].add(Q); } // convert the table to affine if (ROM.CURVETYPE == ROM.WEIERSTRASS) { multiaffine(8, W); } // make exponent odd - add 2P if even, P if odd t.copy(e); s = t.parity(); t.inc(1); t.norm(); ns = t.parity(); mt.copy(t); mt.inc(1); mt.norm(); t.cmove(mt, s); Q.cmove(this, ns); C.copy(Q); nb = 1 + (t.nbits() + 3) / 4; // convert exponent to signed 4-bit window for (i = 0; i < nb; i++) { w[i] = (sbyte)(t.lastbits(5) - 16); t.dec(w[i]); t.norm(); t.fshr(4); } w[nb] = (sbyte)t.lastbits(5); P.copy(W[(w[nb] - 1) / 2]); for (i = nb - 1; i >= 0; i--) { Q.select(W, w[i]); P.dbl(); P.dbl(); P.dbl(); P.dbl(); P.add(Q); } P.sub(C); // apply correction } P.affine(); return(P); }
/* test this=0? */ public bool iszilch() { reduce(); return(x.iszilch()); }