/* convert from byte array to point */ public static ECP2 fromBytes(sbyte[] b) { sbyte[] t = new sbyte[ROM.MODBYTES]; BIG ra; BIG rb; for (int i = 0; i < ROM.MODBYTES; i++) { t[i] = b[i]; } ra = BIG.fromBytes(t); for (int i = 0; i < ROM.MODBYTES; i++) { t[i] = b[i + ROM.MODBYTES]; } rb = BIG.fromBytes(t); FP2 rx = new FP2(ra, rb); for (int i = 0; i < ROM.MODBYTES; i++) { t[i] = b[i + 2 * ROM.MODBYTES]; } ra = BIG.fromBytes(t); for (int i = 0; i < ROM.MODBYTES; i++) { t[i] = b[i + 3 * ROM.MODBYTES]; } rb = BIG.fromBytes(t); FP2 ry = new FP2(ra, rb); return(new ECP2(rx, ry)); }
/* * 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); }
/* 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); }
/* 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)); } }
/* 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); }
/* Time Permit CTT=S*(date|H(CID)) where S is master secret */ public static int GET_CLIENT_PERMIT(int date, sbyte[] S, sbyte[] CID, sbyte[] CTT) { sbyte[] h = hashit(date, CID); ECP P = mapit(h); BIG s = BIG.fromBytes(S); PAIR.G1mul(P, s).toBytes(CTT); return(0); }
/* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */ public static int GET_SERVER_SECRET(sbyte[] S, sbyte[] SST) { 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))); BIG s = BIG.fromBytes(S); Q = PAIR.G2mul(Q, s); Q.toBytes(SST); return(0); }
/* 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); }
/* these next two functions implement elligator squared - http://eprint.iacr.org/2014/043 */ /* Elliptic curve point E in format (0x04,x,y} is converted to form {0x0-,u,v} */ /* Note that u and v are indistinguisible from random strings */ public static int ENCODING(RAND rng, sbyte[] E) { int rn, m, su, sv; sbyte[] T = new sbyte[EFS]; for (int i = 0; i < EFS; i++) { T[i] = E[i + 1]; } BIG u = BIG.fromBytes(T); for (int i = 0; i < EFS; i++) { T[i] = E[i + EFS + 1]; } BIG v = BIG.fromBytes(T); ECP P = new ECP(u, v); if (P.is_infinity()) { return(INVALID_POINT); } BIG p = new BIG(ROM.Modulus); u = BIG.randomnum(p, rng); su = rng.Byte; //if (su<0) su=-su; su %= 2; ECP W = map(u, su); P.sub(W); sv = P.S; rn = unmap(v, P); m = rng.Byte; //if (m<0) m=-m; m %= rn; v.inc(m + 1); E[0] = (sbyte)(su + 2 * sv); u.toBytes(T); for (int i = 0; i < EFS; i++) { E[i + 1] = T[i]; } v.toBytes(T); for (int i = 0; i < EFS; i++) { E[i + EFS + 1] = T[i]; } return(0); }
/* 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); }
public static int DECODING(sbyte[] D) { int su, sv; sbyte[] T = new sbyte[EFS]; if ((D[0] & 0x04) != 0) { return(INVALID_POINT); } for (int i = 0; i < EFS; i++) { T[i] = D[i + 1]; } BIG u = BIG.fromBytes(T); for (int i = 0; i < EFS; i++) { T[i] = D[i + EFS + 1]; } BIG v = BIG.fromBytes(T); su = D[0] & 1; sv = (D[0] >> 1) & 1; ECP W = map(u, su); ECP P = map(v, sv); P.add(W); u = P.X; v = P.Y; D[0] = 0x04; u.toBytes(T); for (int i = 0; i < EFS; i++) { D[i + 1] = T[i]; } v.toBytes(T); for (int i = 0; i < EFS; i++) { D[i + EFS + 1] = T[i]; } 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); }
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); }
/* Calculate a public/private EC GF(p) key pair W,S where W=S.G mod EC(p), * where S is the secret key and W is the public key * and G is fixed generator. * If RNG is NULL then the private key is provided externally in S * otherwise it is generated randomly internally */ public static int KEY_PAIR_GENERATE(RAND RNG, sbyte[] S, sbyte[] W) { BIG r, gx, gy, s; ECP G, WP; int res = 0; sbyte[] T = new sbyte[EFS]; gx = new BIG(ROM.CURVE_Gx); if (ROM.CURVETYPE != ROM.MONTGOMERY) { gy = new BIG(ROM.CURVE_Gy); G = new ECP(gx, gy); } else { G = new ECP(gx); } r = new BIG(ROM.CURVE_Order); if (RNG == null) { s = BIG.fromBytes(S); } else { s = BIG.randomnum(r, RNG); s.toBytes(T); for (int i = 0; i < EGS; i++) { S[i] = T[i]; } } WP = G.mul(s); WP.toBytes(W); 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); }
/* 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); }
/* 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); }
/* convert from byte array to FP12 */ public static FP12 fromBytes(sbyte[] w) { BIG a, b; FP2 c, d; FP4 e, f, g; sbyte[] t = new sbyte[ROM.MODBYTES]; for (int i = 0; i < ROM.MODBYTES; i++) { t[i] = w[i]; } a = BIG.fromBytes(t); for (int i = 0; i < ROM.MODBYTES; i++) { t[i] = w[i + ROM.MODBYTES]; } b = BIG.fromBytes(t); c = new FP2(a, b); for (int i = 0; i < ROM.MODBYTES; i++) { t[i] = w[i + 2 * ROM.MODBYTES]; } a = BIG.fromBytes(t); for (int i = 0; i < ROM.MODBYTES; i++) { t[i] = w[i + 3 * ROM.MODBYTES]; } b = BIG.fromBytes(t); d = new FP2(a, b); e = new FP4(c, d); for (int i = 0; i < ROM.MODBYTES; i++) { t[i] = w[i + 4 * ROM.MODBYTES]; } a = BIG.fromBytes(t); for (int i = 0; i < ROM.MODBYTES; i++) { t[i] = w[i + 5 * ROM.MODBYTES]; } b = BIG.fromBytes(t); c = new FP2(a, b); for (int i = 0; i < ROM.MODBYTES; i++) { t[i] = w[i + 6 * ROM.MODBYTES]; } a = BIG.fromBytes(t); for (int i = 0; i < ROM.MODBYTES; i++) { t[i] = w[i + 7 * ROM.MODBYTES]; } b = BIG.fromBytes(t); d = new FP2(a, b); f = new FP4(c, d); for (int i = 0; i < ROM.MODBYTES; i++) { t[i] = w[i + 8 * ROM.MODBYTES]; } a = BIG.fromBytes(t); for (int i = 0; i < ROM.MODBYTES; i++) { t[i] = w[i + 9 * ROM.MODBYTES]; } b = BIG.fromBytes(t); c = new FP2(a, b); for (int i = 0; i < ROM.MODBYTES; i++) { t[i] = w[i + 10 * ROM.MODBYTES]; } a = BIG.fromBytes(t); for (int i = 0; i < ROM.MODBYTES; i++) { t[i] = w[i + 11 * ROM.MODBYTES]; } b = BIG.fromBytes(t); d = new FP2(a, b); g = new FP4(c, d); return(new FP12(e, f, g)); }
/* 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); }