/* 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); }
/* * W=x*H(G); * if RNG == NULL then X is passed in * if RNG != NULL the X is passed out * if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve */ public static int GET_G1_MULTIPLE(RAND rng, int type, sbyte[] X, sbyte[] G, sbyte[] W) { BIG x; BIG r = new BIG(ROM.CURVE_Order); if (rng != null) { x = BIG.randomnum(r, rng); x.toBytes(X); } else { x = BIG.fromBytes(X); } ECP P; if (type == 0) { P = ECP.fromBytes(G); if (P.is_infinity()) { return(INVALID_POINT); } } else { P = mapit(G); } PAIR.G1mul(P, x).toBytes(W); return(0); }
/* Functions to support M-Pin Full */ public static int PRECOMPUTE(sbyte[] TOKEN, sbyte[] CID, sbyte[] G1, sbyte[] G2) { ECP P, T; FP12 g; T = ECP.fromBytes(TOKEN); if (T.is_infinity()) { return(INVALID_POINT); } P = mapit(CID); ECP2 Q = new ECP2(new FP2(new BIG(ROM.CURVE_Pxa), new BIG(ROM.CURVE_Pxb)), new FP2(new BIG(ROM.CURVE_Pya), new BIG(ROM.CURVE_Pyb))); g = PAIR.ate(Q, T); g = PAIR.fexp(g); g.toBytes(G1); g = PAIR.ate(Q, P); g = PAIR.fexp(g); g.toBytes(G2); return(0); }
/* R=R1+R2 in group G1 */ public static int RECOMBINE_G1(sbyte[] R1, sbyte[] R2, sbyte[] R) { ECP P = ECP.fromBytes(R1); ECP Q = ECP.fromBytes(R2); if (P.is_infinity() || Q.is_infinity()) { return(INVALID_POINT); } P.add(Q); P.toBytes(R); 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); }
/* Extract PIN from TOKEN for identity CID */ public static int EXTRACT_PIN(sbyte[] CID, int pin, sbyte[] TOKEN) { ECP P = ECP.fromBytes(TOKEN); if (P.is_infinity()) { return(INVALID_POINT); } sbyte[] h = hashit(0, CID); ECP R = mapit(h); pin %= MAXPIN; R = R.pinmul(pin, PBLEN); P.sub(R); P.toBytes(TOKEN); return(0); }
/* validate public key. Set full=true for fuller check */ public static int PUBLIC_KEY_VALIDATE(bool full, sbyte[] W) { BIG r; ECP WP = ECP.fromBytes(W); int res = 0; r = new BIG(ROM.CURVE_Order); if (WP.is_infinity()) { res = INVALID_PUBLIC_KEY; } if (res == 0 && full) { WP = WP.mul(r); if (!WP.is_infinity()) { res = INVALID_PUBLIC_KEY; } } return(res); }
/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */ public static int ECPSVDP_DH(sbyte[] S, sbyte[] WD, sbyte[] Z) { BIG r, s; ECP W; int res = 0; sbyte[] T = new sbyte[EFS]; s = BIG.fromBytes(S); W = ECP.fromBytes(WD); if (W.is_infinity()) { res = ERROR; } if (res == 0) { r = new BIG(ROM.CURVE_Order); s.mod(r); W = W.mul(s); if (W.is_infinity()) { res = ERROR; } else { W.X.toBytes(T); for (int i = 0; i < EFS; i++) { Z[i] = T[i]; } } } return(res); }
/* calculate common key on server side */ /* Z=r.A - no time permits involved */ public static int SERVER_KEY(sbyte[] Z, sbyte[] SST, sbyte[] W, sbyte[] xID, sbyte[] xCID, sbyte[] SK) { HASH H = new HASH(); sbyte[] t = new sbyte[EFS]; ECP2 sQ = ECP2.fromBytes(SST); if (sQ.is_infinity()) { return(INVALID_POINT); } ECP R = ECP.fromBytes(Z); if (R.is_infinity()) { return(INVALID_POINT); } ECP U; if (xCID != null) { U = ECP.fromBytes(xCID); } else { U = ECP.fromBytes(xID); } if (U.is_infinity()) { return(INVALID_POINT); } BIG w = BIG.fromBytes(W); U = PAIR.G1mul(U, w); FP12 g = PAIR.ate(sQ, R); g = PAIR.fexp(g); FP4 c = g.trace(); 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); U.X.toBytes(t); H.process_array(t); U.Y.toBytes(t); H.process_array(t); t = H.hash(); for (int i = 0; i < PAS; i++) { SK[i] = t[i]; } return(0); }
/* 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); }
/* Implement step 2 of MPin protocol on server side */ public static int SERVER_2(int date, sbyte[] HID, sbyte[] HTID, sbyte[] Y, sbyte[] SST, sbyte[] xID, sbyte[] xCID, sbyte[] mSEC, sbyte[] E, sbyte[] F) { BIG q = new BIG(ROM.Modulus); ECP2 Q = new ECP2(new FP2(new BIG(ROM.CURVE_Pxa), new BIG(ROM.CURVE_Pxb)), new FP2(new BIG(ROM.CURVE_Pya), new BIG(ROM.CURVE_Pyb))); ECP2 sQ = ECP2.fromBytes(SST); if (sQ.is_infinity()) { return(INVALID_POINT); } ECP R; if (date != 0) { R = ECP.fromBytes(xCID); } else { if (xID == null) { return(BAD_PARAMS); } R = ECP.fromBytes(xID); } if (R.is_infinity()) { return(INVALID_POINT); } BIG y = BIG.fromBytes(Y); ECP P; if (date != 0) { P = ECP.fromBytes(HTID); } else { if (HID == null) { return(BAD_PARAMS); } P = ECP.fromBytes(HID); } if (P.is_infinity()) { return(INVALID_POINT); } P = PAIR.G1mul(P, y); P.add(R); R = ECP.fromBytes(mSEC); if (R.is_infinity()) { return(INVALID_POINT); } FP12 g; // FP12 g1=new FP12(0); g = PAIR.ate2(Q, R, sQ, P); g = PAIR.fexp(g); if (!g.isunity()) { if (HID != null && xID != null && E != null && F != null) { g.toBytes(E); if (date != 0) { P = ECP.fromBytes(HID); if (P.is_infinity()) { return(INVALID_POINT); } R = ECP.fromBytes(xID); if (R.is_infinity()) { return(INVALID_POINT); } P = PAIR.G1mul(P, y); P.add(R); } g = PAIR.ate(Q, P); g = PAIR.fexp(g); g.toBytes(F); } return(BAD_PIN); } return(0); }
/* Implement step 1 on client side of MPin protocol */ public static int CLIENT_1(int date, sbyte[] CLIENT_ID, RAND rng, sbyte[] X, int pin, sbyte[] TOKEN, sbyte[] SEC, sbyte[] xID, sbyte[] xCID, sbyte[] PERMIT) { BIG r = new BIG(ROM.CURVE_Order); // BIG q=new BIG(ROM.Modulus); BIG x; // BIG m=new BIG(0); if (rng != null) { x = BIG.randomnum(r, rng); x.toBytes(X); } else { x = BIG.fromBytes(X); } ECP P, T, W; BIG px; // byte[] t=new byte[EFS]; sbyte[] h = hashit(0, CLIENT_ID); P = mapit(h); T = ECP.fromBytes(TOKEN); if (T.is_infinity()) { return(INVALID_POINT); } pin %= MAXPIN; W = P.pinmul(pin, PBLEN); T.add(W); if (date != 0) { W = ECP.fromBytes(PERMIT); if (W.is_infinity()) { return(INVALID_POINT); } T.add(W); h = hashit(date, h); W = mapit(h); if (xID != null) { P = PAIR.G1mul(P, x); P.toBytes(xID); W = PAIR.G1mul(W, x); P.add(W); } else { P.add(W); P = PAIR.G1mul(P, x); } if (xCID != null) { P.toBytes(xCID); } } else { if (xID != null) { P = PAIR.G1mul(P, x); P.toBytes(xID); } } T.toBytes(SEC); return(0); }