/* convert from byte array to point */ public static ECP fromBytes(sbyte[] b) { sbyte[] t = new sbyte[ROM.MODBYTES]; BIG p = new BIG(ROM.Modulus); for (int i = 0; i < ROM.MODBYTES; i++) { t[i] = b[i + 1]; } BIG px = BIG.fromBytes(t); if (BIG.comp(px, p) >= 0) { return(new ECP()); } if (b[0] == 0x04) { for (int i = 0; i < ROM.MODBYTES; i++) { t[i] = b[i + ROM.MODBYTES + 1]; } BIG py = BIG.fromBytes(t); if (BIG.comp(py, p) >= 0) { return(new ECP()); } return(new ECP(px, py)); } else { return(new ECP(px)); } }
/* 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); }
/* return TRUE if this==a */ public bool Equals(FP a) { a.reduce(); reduce(); if (BIG.comp(a.x, x) == 0) { return(true); } return(false); }
/* compare x and y - must be normalised, and of same length */ public static int comp(FF a, FF b) { int i, j; for (i = a.length - 1; i >= 0; i--) { j = BIG.comp(a.v[i], b.v[i]); if (j != 0) { return(j); } } return(0); }
/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */ public FP4 xtr_pow2(FP4 ck, FP4 ckml, FP4 ckm2l, BIG a, BIG b) { a.norm(); b.norm(); BIG e = new BIG(a); BIG d = new BIG(b); BIG w = new BIG(0); FP4 cu = new FP4(ck); // can probably be passed in w/o copying FP4 cv = new FP4(this); FP4 cumv = new FP4(ckml); FP4 cum2v = new FP4(ckm2l); FP4 r = new FP4(0); FP4 t = new FP4(0); int f2 = 0; while (d.parity() == 0 && e.parity() == 0) { d.fshr(1); e.fshr(1); f2++; } while (BIG.comp(d, e) != 0) { if (BIG.comp(d, e) > 0) { w.copy(e); w.imul(4); w.norm(); if (BIG.comp(d, w) <= 0) { w.copy(d); d.copy(e); e.rsub(w); e.norm(); t.copy(cv); t.xtr_A(cu, cumv, cum2v); cum2v.copy(cumv); cum2v.conj(); cumv.copy(cv); cv.copy(cu); cu.copy(t); } else if (d.parity() == 0) { d.fshr(1); r.copy(cum2v); r.conj(); t.copy(cumv); t.xtr_A(cu, cv, r); cum2v.copy(cumv); cum2v.xtr_D(); cumv.copy(t); cu.xtr_D(); } else if (e.parity() == 1) { d.sub(e); d.norm(); d.fshr(1); t.copy(cv); t.xtr_A(cu, cumv, cum2v); cu.xtr_D(); cum2v.copy(cv); cum2v.xtr_D(); cum2v.conj(); cv.copy(t); } else { w.copy(d); d.copy(e); d.fshr(1); e.copy(w); t.copy(cumv); t.xtr_D(); cumv.copy(cum2v); cumv.conj(); cum2v.copy(t); cum2v.conj(); t.copy(cv); t.xtr_D(); cv.copy(cu); cu.copy(t); } } if (BIG.comp(d, e) < 0) { w.copy(d); w.imul(4); w.norm(); if (BIG.comp(e, w) <= 0) { e.sub(d); e.norm(); t.copy(cv); t.xtr_A(cu, cumv, cum2v); cum2v.copy(cumv); cumv.copy(cu); cu.copy(t); } else if (e.parity() == 0) { w.copy(d); d.copy(e); d.fshr(1); e.copy(w); t.copy(cumv); t.xtr_D(); cumv.copy(cum2v); cumv.conj(); cum2v.copy(t); cum2v.conj(); t.copy(cv); t.xtr_D(); cv.copy(cu); cu.copy(t); } else if (d.parity() == 1) { w.copy(e); e.copy(d); w.sub(d); w.norm(); d.copy(w); d.fshr(1); t.copy(cv); t.xtr_A(cu, cumv, cum2v); cumv.conj(); cum2v.copy(cu); cum2v.xtr_D(); cum2v.conj(); cu.copy(cv); cu.xtr_D(); cv.copy(t); } else { d.fshr(1); r.copy(cum2v); r.conj(); t.copy(cumv); t.xtr_A(cu, cv, r); cum2v.copy(cumv); cum2v.xtr_D(); cumv.copy(t); cu.xtr_D(); } } } r.copy(cv); r.xtr_A(cu, cumv, cum2v); for (int i = 0; i < f2; i++) { r.xtr_D(); } r = r.xtr_pow(d); return(r); }