/* 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); }
/* * 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); }
/* constant time multiply by small integer of length bts - use ladder */ public ECP pinmul(int e, int bts) { if (ROM.CURVETYPE == ROM.MONTGOMERY) { return(this.mul(new BIG(e))); } else { int nb, i, b; ECP P = new ECP(); ECP R0 = new ECP(); ECP R1 = new ECP(); R1.copy(this); for (i = bts - 1; i >= 0; i--) { b = (e >> i) & 1; P.copy(R1); P.add(R0); R0.cswap(R1, b); R1.copy(P); R0.dbl(); R0.cswap(R1, b); } P.copy(R0); P.affine(); return(P); } }
/* 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); }
/* 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); }
/** * Verify a WBB signature for a certain message * * @param pk Public key * @param sig Signature * @param m Message * @return True iff valid */ public static bool weakBBVerify(ECP2 pk, ECP sig, BIG m) { ECP2 p = new ECP2(); p.Copy(pk); p.Add(IdemixUtils.GenG2.Mul(m)); p.Affine(); return(PAIR.FExp(PAIR.Ate(p, sig)).Equals(IdemixUtils.GenGT)); }
/* this=P */ public void copy(ECP P) { x.copy(P.x); if (ROM.CURVETYPE != ROM.MONTGOMERY) { y.copy(P.y); } z.copy(P.z); INF = P.INF; }
/* 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); }
/* Optimal R-ate pairing */ public static FP12 ate(ECP2 P, ECP Q) { FP2 f = new FP2(new BIG(ROM.CURVE_Fra), new BIG(ROM.CURVE_Frb)); BIG x = new BIG(ROM.CURVE_Bnx); BIG n = new BIG(x); ECP2 K = new ECP2(); FP12 lv; n.pmul(6); n.dec(2); n.norm(); P.affine(); Q.affine(); FP Qx = new FP(Q.getx()); FP Qy = new FP(Q.gety()); ECP2 A = new ECP2(); FP12 r = new FP12(1); A.copy(P); int nb = n.nbits(); for (int i = nb - 2; i >= 1; i--) { lv = line(A, A, Qx, Qy); r.smul(lv); if (n.bit(i) == 1) { lv = line(A, P, Qx, Qy); r.smul(lv); } r.sqr(); } lv = line(A, A, Qx, Qy); r.smul(lv); /* R-ate fixup */ r.conj(); K.copy(P); K.frob(f); A.neg(); lv = line(A, K, Qx, Qy); r.smul(lv); K.frob(f); K.neg(); lv = line(A, K, Qx, Qy); r.smul(lv); return(r); }
/* 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); }
/** * Converts an amcl.BN256.ECP into an ECP protobuf object. * * @param w an ECP to be transformed into a protobuf object * @return a protobuf representation of the ECP */ public static Protos.Idemix.ECP ToProto(this ECP w) { byte[] valueX = new byte[FIELD_BYTES]; byte[] valueY = new byte[FIELD_BYTES]; w.X.ToBytes(valueX); w.Y.ToBytes(valueY); Protos.Idemix.ECP ecp = new Protos.Idemix.ECP(); ecp.X = ByteString.CopyFrom(valueX); ecp.Y = ByteString.CopyFrom(valueY); return(ecp); }
public EMHCrypt01(GetMeterDelegate GetMeter, CheckMeterPublicKeySignatureDelegate CheckMeterPublicKeySignature) : base("ECC secp192r1", GetMeter, CheckMeterPublicKeySignature) { this.CurveName = "P-192"; this.ECP = ECNamedCurveTable.GetByName(CurveName); this.ECSpec = new ECDomainParameters(ECP.Curve, ECP.G, ECP.N, ECP.H, ECP.GetSeed()); this.C = (FpCurve)ECSpec.Curve; }
/* 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); }
/* Multiply P by e in group G1 */ public static ECP G1Mul(ECP P, BIG e) { ECP R; if (USE_GLV) { //P.affine(); R = new ECP(); R.Copy(P); int np, nn; ECP Q = new ECP(); Q.Copy(P); Q.Affine(); BIG q = new BIG(ROM.CURVE_Order); FP cru = new FP(new BIG(ROM.CURVE_Cru)); BIG t = new BIG(0); BIG[] u = Glv(e); Q.GetX().Mul(cru); np = u[0].NBits(); t.Copy(BIG.ModNeg(u[0], q)); nn = t.NBits(); if (nn < np) { u[0].Copy(t); R.Neg(); } np = u[1].NBits(); t.Copy(BIG.ModNeg(u[1], q)); nn = t.NBits(); if (nn < np) { u[1].Copy(t); Q.Neg(); } u[0].Norm(); u[1].Norm(); R = R.Mul2(u[0], Q, u[1]); } else { R = P.Mul(e); } return(R); }
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); }
/* Multiply P by e in group G1 */ public static ECP G1mul(ECP P, BIG e) { ECP R; if (ROM.USE_GLV) { P.affine(); R = new ECP(); R.copy(P); int i, np, nn; ECP Q = new ECP(); Q.copy(P); BIG q = new BIG(ROM.CURVE_Order); FP cru = new FP(new BIG(ROM.CURVE_Cru)); BIG t = new BIG(0); BIG[] u = glv(e); Q.getx().mul(cru); np = u[0].nbits(); t.copy(BIG.modneg(u[0], q)); nn = t.nbits(); if (nn < np) { u[0].copy(t); R.neg(); } np = u[1].nbits(); t.copy(BIG.modneg(u[1], q)); nn = t.nbits(); if (nn < np) { u[1].copy(t); Q.neg(); } R = R.mul2(u[0], Q, u[1]); } else { R = P.mul(e); } return(R); }
/* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */ public void dadd(ECP Q, ECP W) { FP A = new FP(x); FP B = new FP(x); FP C = new FP(Q.x); FP D = new FP(Q.x); FP DA = new FP(0); FP CB = new FP(0); A.add(z); B.sub(z); C.add(Q.z); D.sub(Q.z); DA.copy(D); DA.mul(A); CB.copy(C); CB.mul(B); A.copy(DA); A.add(CB); A.sqr(); B.copy(DA); B.sub(CB); B.sqr(); x.copy(A); z.copy(W.x); z.mul(B); if (z.iszilch()) { inf(); } else { INF = false; } // x.reduce(); x.norm(); }
/* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */ /* maps a random u to a point on the curve */ public static ECP map(BIG u, int cb) { ECP P; BIG x = new BIG(u); BIG p = new BIG(ROM.Modulus); x.mod(p); while (true) { P = new ECP(x, cb); if (!P.is_infinity()) { break; } x.inc(1); x.norm(); } return(P); }
/* 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); }
/* returns u derived from P. Random value in range 1 to return value should then be added to u */ public static int unmap(BIG u, ECP P) { int s = P.S; ECP R; int r = 0; BIG x = P.X; u.copy(x); while (true) { u.dec(1); u.norm(); r++; R = new ECP(u, s); if (!R.is_infinity()) { break; } } return(r); }
/* Constant time select from pre-computed table */ private void select(ECP[] W, int b) { ECP MP = new ECP(); int m = b >> 31; int babs = (b ^ m) - m; babs = (babs - 1) / 2; cmove(W[0], teq(babs, 0)); // conditional move cmove(W[1], teq(babs, 1)); cmove(W[2], teq(babs, 2)); cmove(W[3], teq(babs, 3)); cmove(W[4], teq(babs, 4)); cmove(W[5], teq(babs, 5)); cmove(W[6], teq(babs, 6)); cmove(W[7], teq(babs, 7)); MP.copy(this); MP.neg(); cmove(MP, (int)(m & 1)); }
/* 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); }
/* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */ public static void SERVER_1(int date, sbyte[] CID, sbyte[] HID, sbyte[] HTID) { sbyte[] h = hashit(0, CID); ECP R, P = mapit(h); if (date != 0) { if (HID != null) { P.toBytes(HID); } h = hashit(date, h); R = mapit(h); P.add(R); P.toBytes(HTID); } else { P.toBytes(HID); } }
/* Conditional move of Q to P dependant on d */ private void cmove(ECP Q, int d) { x.cmove(Q.x, d); if (ROM.CURVETYPE != ROM.MONTGOMERY) { y.cmove(Q.y, d); } z.cmove(Q.z, d); if (ROM.CURVETYPE != ROM.EDWARDS) { bool bd; if (d == 0) { bd = false; } else { bd = true; } INF ^= (INF ^ Q.INF) & bd; } }
/* 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); }
/* Conditional swap of P and Q dependant on d */ private void cswap(ECP Q, int d) { x.cswap(Q.x, d); if (ROM.CURVETYPE != ROM.MONTGOMERY) { y.cswap(Q.y, d); } z.cswap(Q.z, d); if (ROM.CURVETYPE != ROM.EDWARDS) { bool bd; if (d == 0) { bd = false; } else { bd = true; } bd = bd & (INF ^ Q.INF); INF ^= bd; Q.INF ^= bd; } }
/* 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); }
/* 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); }