/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */ public static int ECPVP_DSA(sbyte[] W, sbyte[] F, sbyte[] C, sbyte[] D) { BIG r, gx, gy, f, c, d, h2; int res = 0; ECP G, WP, P; 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); c = BIG.fromBytes(C); d = BIG.fromBytes(D); f = BIG.fromBytes(B); if (c.iszilch() || BIG.comp(c, r) >= 0 || d.iszilch() || BIG.comp(d, r) >= 0) { res = INVALID; } if (res == 0) { d.invmodp(r); f.copy(BIG.modmul(f, d, r)); h2 = BIG.modmul(c, d, r); WP = ECP.fromBytes(W); if (WP.is_infinity()) { res = ERROR; } else { P = new ECP(); P.copy(WP); P = P.mul2(h2, G, f); if (P.is_infinity()) { res = INVALID; } else { d = P.X; d.mod(r); if (BIG.comp(d, c) != 0) { res = INVALID; } } } } return(res); }
/* Galbraith & Scott Method */ public static BIG[] gs(BIG e) { int i, j; BIG t = new BIG(0); BIG q = new BIG(ROM.CURVE_Order); BIG[] u = new BIG[4]; BIG[] v = new BIG[4]; for (i = 0; i < 4; i++) { t.copy(new BIG(ROM.CURVE_WB[i])); DBIG d = BIG.mul(t, e); v[i] = new BIG(d.div(q)); u[i] = new BIG(0); } u[0].copy(e); for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { t.copy(new BIG(ROM.CURVE_BB[j][i])); t.copy(BIG.modmul(v[j], t, q)); u[i].add(q); u[i].sub(t); u[i].mod(q); } } return(u); }
/* GLV method */ public static BIG[] glv(BIG e) { int i, j; BIG t = new BIG(0); BIG q = new BIG(ROM.CURVE_Order); BIG[] u = new BIG[2]; BIG[] v = new BIG[2]; for (i = 0; i < 2; i++) { t.copy(new BIG(ROM.CURVE_W[i])); // why not just t=new BIG(ROM.CURVE_W[i]); DBIG d = BIG.mul(t, e); v[i] = new BIG(d.div(q)); u[i] = new BIG(0); } u[0].copy(e); for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { t.copy(new BIG(ROM.CURVE_SB[j][i])); t.copy(BIG.modmul(v[j], t, q)); u[i].add(q); u[i].sub(t); u[i].mod(q); } } return(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); }