/* return number of bits */ public virtual int NBits() { BIG t = new BIG(this); int bts, k = NLEN - 1; long c; t.Norm(); while (k >= 0 && t.w[k] == 0) { k--; } if (k < 0) { return(0); } bts = BASEBITS * k; c = t.w[k]; while (c != 0) { c /= 2; bts++; } return(bts); }
/* reduce this mod m */ public virtual void Mod(BIG m1) { int k = 0; BIG r = new BIG(0); BIG m = new BIG(m1); Norm(); if (Comp(this, m) < 0) { return; } do { m.FShl(1); k++; } while (Comp(this, m) >= 0); while (k > 0) { m.FShr(1); r.Copy(this); r.Sub(m); r.Norm(); CMove(r, (int)(1 - ((r.w[NLEN - 1] >> (CHUNK - 1)) & 1))); k--; } }
/* return this^e mod m */ public virtual BIG PowMod(BIG e1, BIG m) { BIG e = new BIG(e1); int bt; Norm(); e.Norm(); BIG a = new BIG(1); BIG z = new BIG(e); BIG s = new BIG(this); while (true) { bt = z.Parity(); z.FShr(1); if (bt == 1) { a = ModMul(a, s, m); } if (z.IsZilch()) { break; } s = ModSqr(s, m); } return(a); }
/* a=1/a mod 2^256. This is very fast! */ public virtual void InvMod2m() { int i; BIG U = new BIG(0); BIG b = new BIG(0); BIG c = new BIG(0); U.Inc(InvMod256(LastBits(8))); for (i = 8; i < BIGBITS; i <<= 1) { U.Norm(); b.Copy(this); b.Mod2m(i); BIG t1 = SMul(U, b); t1.Shr(i); c.Copy(this); c.Shr(i); c.Mod2m(i); BIG t2 = SMul(U, c); t2.Mod2m(i); t1.Add(t2); t1.Norm(); b = SMul(t1, U); t1.Copy(b); t1.Mod2m(i); t2.One(); t2.Shl(i); t1.RSub(t2); t1.Norm(); t1.Shl(i); U.Add(t1); } U.Mod2m(BIGBITS); Copy(U); Norm(); }
/* convert this BIG to byte array */ public virtual void ToByteArray(sbyte[] b, int n) { BIG c = new BIG(this); c.Norm(); for (int i = MODBYTES - 1; i >= 0; i--) { b[i + n] = (sbyte)c.w[0]; c.FShr(8); } }
/* divide this by m */ public virtual void Div(BIG m1) { int d, k = 0; Norm(); BIG e = new BIG(1); BIG m = new BIG(m1); BIG b = new BIG(this); BIG r = new BIG(0); Zero(); while (Comp(b, m) >= 0) { e.FShl(1); m.FShl(1); k++; } while (k > 0) { m.FShr(1); e.FShr(1); r.Copy(b); r.Sub(m); r.Norm(); d = (int)(1 - ((r.w[NLEN - 1] >> (CHUNK - 1)) & 1)); b.CMove(r, d); r.Copy(this); r.Add(e); r.Norm(); CMove(r, d); k--; } }
internal static BIG Monty(BIG md, long MC, DBIG d) { BIG b; long m, carry; long[] cr = new long[2]; for (int i = 0; i < NLEN; i++) { if (MC == -1) { m = -d.w[i] & BMASK; } else { if (MC == 1) { m = d.w[i]; } else { m = (MC * d.w[i]) & BMASK; } } carry = 0; for (int j = 0; j < NLEN; j++) { cr = MulAdd(m, md.w[j], carry, d.w[i + j]); carry = cr[0]; d.w[i + j] = cr[1]; } d.w[NLEN + i] += carry; } b = new BIG(0); for (int i = 0; i < NLEN; i++) { b.w[i] = d.w[NLEN + i]; } b.Norm(); return(b); }
/* Map byte string to curve point */ public static ECP MapIt(sbyte[] h) { BIG q = new BIG(ROM.Modulus); BIG x = BIG.FromBytes(h); x.Mod(q); ECP P; while (true) { while (true) { if (CURVETYPE != MONTGOMERY) { P = new ECP(x, 0); } else { P = new ECP(x); } x.Inc(1); x.Norm(); if (!P.IsInfinity()) { break; } } P.Cfp(); if (!P.IsInfinity()) { break; } } return(P); }
/* Return e.this+f.Q */ public ECP Mul2(BIG e, ECP Q, BIG f) { BIG te = new BIG(); BIG tf = new BIG(); BIG mt = new BIG(); ECP S = new ECP(); ECP T = new ECP(); ECP C = new ECP(); ECP[] W = new ECP[8]; sbyte[] w = new sbyte[1 + (BIG.NLEN * BIG.BASEBITS + 1) / 2]; int i, s, ns, nb; sbyte a, b; //affine(); //Q.affine(); te.Copy(e); tf.Copy(f); // precompute table W[1] = new ECP(); W[1].Copy(this); W[1].Sub(Q); W[2] = new ECP(); W[2].Copy(this); W[2].Add(Q); S.Copy(Q); S.Dbl(); W[0] = new ECP(); W[0].Copy(W[1]); W[0].Sub(S); W[3] = new ECP(); W[3].Copy(W[2]); W[3].Add(S); T.Copy(this); T.Dbl(); W[5] = new ECP(); W[5].Copy(W[1]); W[5].Add(T); W[6] = new ECP(); W[6].Copy(W[2]); W[6].Add(T); W[4] = new ECP(); W[4].Copy(W[5]); W[4].Sub(S); W[7] = new ECP(); W[7].Copy(W[6]); W[7].Add(S); // if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction s = te.Parity(); te.Inc(1); te.Norm(); ns = te.Parity(); mt.Copy(te); mt.Inc(1); mt.Norm(); te.CMove(mt, s); T.CMove(this, ns); C.Copy(T); s = tf.Parity(); tf.Inc(1); tf.Norm(); ns = tf.Parity(); mt.Copy(tf); mt.Inc(1); mt.Norm(); tf.CMove(mt, s); S.CMove(Q, ns); C.Add(S); mt.Copy(te); mt.Add(tf); mt.Norm(); nb = 1 + (mt.NBits() + 1) / 2; // convert exponent to signed 2-bit window for (i = 0; i < nb; i++) { a = (sbyte)(te.LastBits(3) - 4); te.Dec(a); te.Norm(); te.FShr(2); b = (sbyte)(tf.LastBits(3) - 4); tf.Dec(b); tf.Norm(); tf.FShr(2); w[i] = (sbyte)(4 * a + b); } w[nb] = (sbyte)(4 * te.LastBits(3) + tf.LastBits(3)); S.Copy(W[(w[nb] - 1) / 2]); for (i = nb - 1; i >= 0; i--) { T.Select(W, w[i]); S.Dbl(); S.Dbl(); S.Add(T); } S.Sub(C); // apply correction S.Affine(); return(S); }
/* return e.this */ public ECP Mul(BIG e) { if (e.IsZilch() || IsInfinity()) { return(new ECP()); } ECP P = new ECP(); if (CURVETYPE == 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, nb, 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 + (BIG.NLEN * BIG.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); } // 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); }
/* this=1/this mod p. Binary method */ public virtual void InvModp(BIG p) { Mod(p); BIG u = new BIG(this); BIG v = new BIG(p); BIG x1 = new BIG(1); BIG x2 = new BIG(0); BIG t = new BIG(0); BIG one = new BIG(1); while (Comp(u, one) != 0 && Comp(v, one) != 0) { while (u.Parity() == 0) { u.FShr(1); if (x1.Parity() != 0) { x1.Add(p); x1.Norm(); } x1.FShr(1); } while (v.Parity() == 0) { v.FShr(1); if (x2.Parity() != 0) { x2.Add(p); x2.Norm(); } x2.FShr(1); } if (Comp(u, v) >= 0) { u.Sub(v); u.Norm(); if (Comp(x1, x2) >= 0) { x1.Sub(x2); } else { t.Copy(p); t.Sub(x2); x1.Add(t); } x1.Norm(); } else { v.Sub(u); v.Norm(); if (Comp(x2, x1) >= 0) { x2.Sub(x1); } else { t.Copy(p); t.Sub(x1); x2.Add(t); } x2.Norm(); } } if (Comp(u, one) == 0) { Copy(x1); } else { Copy(x2); } }
/* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */ /* * public static ECP2 mul4(ECP2[] Q,BIG[] u) * { * int i,j,nb; * int[] a=new int[4]; * ECP2 T=new ECP2(); * ECP2 C=new ECP2(); * ECP2 P=new ECP2(); * ECP2[] W=new ECP2[8]; * * BIG mt=new BIG(); * BIG[] t=new BIG[4]; * * byte[] w=new byte[BIG.NLEN*BIG.BASEBITS+1]; * * for (i=0;i<4;i++) * { * t[i]=new BIG(u[i]); * Q[i].affine(); * } * * // precompute table * * W[0]=new ECP2(); W[0].copy(Q[0]); W[0].sub(Q[1]); * * W[1]=new ECP2(); W[1].copy(W[0]); * W[2]=new ECP2(); W[2].copy(W[0]); * W[3]=new ECP2(); W[3].copy(W[0]); * W[4]=new ECP2(); W[4].copy(Q[0]); W[4].add(Q[1]); * W[5]=new ECP2(); W[5].copy(W[4]); * W[6]=new ECP2(); W[6].copy(W[4]); * W[7]=new ECP2(); W[7].copy(W[4]); * T.copy(Q[2]); T.sub(Q[3]); * W[1].sub(T); * W[2].add(T); * W[5].sub(T); * W[6].add(T); * T.copy(Q[2]); T.add(Q[3]); * W[0].sub(T); * W[3].add(T); * W[4].sub(T); * W[7].add(T); * * // if multiplier is even add 1 to multiplier, and add P to correction * mt.zero(); C.inf(); * for (i=0;i<4;i++) * { * if (t[i].parity()==0) * { * t[i].inc(1); t[i].norm(); * C.add(Q[i]); * } * mt.add(t[i]); mt.norm(); * } * * nb=1+mt.nbits(); * * // convert exponent to signed 1-bit window * for (j=0;j<nb;j++) * { * for (i=0;i<4;i++) * { * a[i]=(byte)(t[i].lastbits(2)-2); * t[i].dec(a[i]); t[i].norm(); * t[i].fshr(1); * } * w[j]=(byte)(8*a[0]+4*a[1]+2*a[2]+a[3]); * } * w[nb]=(byte)(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2)); * * P.copy(W[(w[nb]-1)/2]); * for (i=nb-1;i>=0;i--) * { * T.select(W,w[i]); * P.dbl(); * P.add(T); * } * P.sub(C); // apply correction * * P.affine(); * return P; * } */ /* needed for SOK */ public static ECP2 MapIt(sbyte[] h) { BIG q = new BIG(ROM.Modulus); BIG x = BIG.FromBytes(h); BIG one = new BIG(1); FP2 X; ECP2 Q; x.Mod(q); while (true) { X = new FP2(one, x); Q = new ECP2(X); if (!Q.IsInfinity()) { break; } x.Inc(1); x.Norm(); } BIG Fra = new BIG(ROM.Fra); BIG Frb = new BIG(ROM.Frb); X = new FP2(Fra, Frb); if (ECP.SEXTIC_TWIST == ECP.M_TYPE) { X.Inverse(); X.Norm(); } x = new BIG(ROM.CURVE_Bnx); /* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */ if (ECP.CURVE_PAIRING_TYPE == ECP.BN) { ECP2 T, K; T = new ECP2(); T.Copy(Q); T = T.Mul(x); if (ECP.SIGN_OF_X == ECP.NEGATIVEX) { 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); } /* Efficient hash maps to G2 on BLS curves - Budroni, Pintore */ /* Q -> x2Q -xQ -Q +F(xQ -Q) +F(F(2Q)) */ if (ECP.CURVE_PAIRING_TYPE == ECP.BLS) { // ECP2 xQ,x2Q; // xQ=new ECP2(); // x2Q=new ECP2(); ECP2 xQ = Q.Mul(x); ECP2 x2Q = xQ.Mul(x); if (ECP.SIGN_OF_X == ECP.NEGATIVEX) { xQ.Neg(); } x2Q.Sub(xQ); x2Q.Sub(Q); xQ.Sub(Q); xQ.Frob(X); Q.Dbl(); Q.Frob(X); Q.Frob(X); Q.Add(x2Q); Q.Add(xQ); } Q.Affine(); return(Q); }
/* P*=e */ public ECP2 Mul(BIG e) { /* fixed size windows */ int i, nb, s, ns; BIG mt = new BIG(); BIG t = new BIG(); ECP2 P = new ECP2(); ECP2 Q = new ECP2(); ECP2 C = new ECP2(); ECP2[] W = new ECP2[8]; sbyte[] w = new sbyte[1 + (BIG.NLEN * BIG.BASEBITS + 3) / 4]; if (IsInfinity()) { return(new ECP2()); } //affine(); /* precompute table */ Q.Copy(this); Q.Dbl(); W[0] = new ECP2(); W[0].Copy(this); for (i = 1; i < 8; i++) { W[i] = new ECP2(); W[i].Copy(W[i - 1]); W[i].Add(Q); } /* 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); P.Affine(); return(P); }