/* Galbraith & Scott Method */ public static BIG[] gs(BIG e) { int i, j; BIG t = new BIG(0); BIG q = new BIG(ROM.CURVE_Order); BIG[] u = new BIG[4]; BIG[] v = new BIG[4]; for (i = 0; i < 4; i++) { t.copy(new BIG(ROM.CURVE_WB[i])); DBIG d = BIG.mul(t, e); v[i] = new BIG(d.div(q)); u[i] = new BIG(0); } u[0].copy(e); for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { t.copy(new BIG(ROM.CURVE_BB[j][i])); t.copy(BIG.modmul(v[j], t, q)); u[i].add(q); u[i].sub(t); u[i].mod(q); } } return(u); }
/* this+=x */ public virtual void Add(DBIG x) { for (int i = 0; i < BIG.DNLEN; i++) { w[i] += x.w[i]; } }
public DBIG(DBIG x) { for (int i = 0; i < ROM.DNLEN; i++) { w[i] = x.w[i]; } }
/* reduces this DBIG mod a BIG, and returns the BIG */ public virtual BIG mod(BIG c) { int k = 0; norm(); DBIG m = new DBIG(c); if (comp(this, m) < 0) { return(new BIG(this)); } do { m.shl(1); k++; } while (comp(this, m) >= 0); while (k > 0) { m.shr(1); if (comp(this, m) >= 0) { sub(m); norm(); } k--; } return(new BIG(this)); }
public virtual void RSub(DBIG x) { for (int i = 0; i < BIG.DNLEN; i++) { w[i] = x.w[i] - w[i]; } }
/* this*=c mod Modulus, where c is a small int */ public void imul(int c) { norm(); bool s = false; if (c < 0) { c = -c; s = true; } long afx = (BIG.EXCESS(x) + 1) * (c + 1) + 1; if (c < ROM.NEXCESS && afx < ROM.FEXCESS) { x.imul(c); } else { if (afx < ROM.FEXCESS) { x.pmul(c); } else { DBIG d = x.pxmul(c); x.copy(d.mod(p)); } } if (s) { neg(); } norm(); }
/* reduces this DBIG mod a BIG, and returns the BIG */ public virtual BIG Mod(BIG c) { int k = 0; Norm(); DBIG m = new DBIG(c); DBIG r = new DBIG(0); if (Comp(this, m) < 0) { return(new BIG(this)); } do { m.Shl(1); k++; } while (Comp(this, m) >= 0); while (k > 0) { m.Shr(1); r.Copy(this); r.Sub(m); r.Norm(); CMove(r, (int)(1 - ((r.w[BIG.DNLEN - 1] >> (BIG.CHUNK - 1)) & 1))); k--; } return(new BIG(this)); }
/* return this+x */ /* * public DBIG plus(DBIG x) { * DBIG s=new DBIG(0); * for (int i=0;i<ROM.DNLEN;i++) * s.w[i]=w[i]+x.w[i]; * return s; * } */ /* return this-x */ /* * public DBIG minus(DBIG x) { * DBIG d=new DBIG(0); * for (int i=0;i<ROM.DNLEN;i++) * d.w[i]=w[i]-x.w[i]; * return d; * } */ /* this+=x */ public virtual void add(DBIG x) { for (int i = 0; i < ROM.DNLEN; i++) { w[i] += x.w[i]; } }
/* return a^2 mod m */ public static BIG modsqr(BIG a, BIG m) { a.mod(m); DBIG d = sqr(a); return(d.mod(m)); }
/* reduces this DBIG mod a DBIG in place */ /* public void mod(DBIG m) * { * int k=0; * if (comp(this,m)<0) return; * * do * { * m.shl(1); * k++; * } * while (comp(this,m)>=0); * * while (k>0) * { * m.shr(1); * if (comp(this,m)>=0) * { * sub(m); * norm(); * } * k--; * } * return; * * }*/ /* return this/c */ public virtual BIG div(BIG c) { int k = 0; DBIG m = new DBIG(c); BIG a = new BIG(0); BIG e = new BIG(1); norm(); while (comp(this, m) >= 0) { e.fshl(1); m.shl(1); k++; } while (k > 0) { m.shr(1); e.shr(1); if (comp(this, m) > 0) { a.add(e); a.norm(); sub(m); norm(); } k--; } return(a); }
public virtual void copy(DBIG x) { for (int i = 0; i < ROM.NLEN; i++) { w[i] = x.w[i]; } }
/* Create random BIG in portable way, one bit at a time */ public static BIG randomnum(BIG q, RAND rng) { DBIG d = new DBIG(0); int i, b, j = 0, r = 0; for (i = 0; i < 2 * ROM.MODBITS; i++) { if (j == 0) { r = rng.Byte; } else { r >>= 1; } b = r & 1; d.shl(1); d.w[0] += b; // m.inc(b); j++; j &= 7; } BIG m = d.mod(q); return(m); }
/* this-=x */ public virtual void sub(DBIG x) { for (int i = 0; i < ROM.DNLEN; i++) { w[i] -= x.w[i]; } }
/* GLV method */ public static BIG[] glv(BIG e) { int i, j; BIG t = new BIG(0); BIG q = new BIG(ROM.CURVE_Order); BIG[] u = new BIG[2]; BIG[] v = new BIG[2]; for (i = 0; i < 2; i++) { t.copy(new BIG(ROM.CURVE_W[i])); // why not just t=new BIG(ROM.CURVE_W[i]); DBIG d = BIG.mul(t, e); v[i] = new BIG(d.div(q)); u[i] = new BIG(0); } u[0].copy(e); for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { t.copy(new BIG(ROM.CURVE_SB[j][i])); t.copy(BIG.modmul(v[j], t, q)); u[i].add(q); u[i].sub(t); u[i].mod(q); } } return(u); }
/* return a*b mod m */ public static BIG modmul(BIG a, BIG b, BIG m) { a.mod(m); b.mod(m); DBIG d = mul(a, b); return(d.mod(m)); }
public virtual void CMove(DBIG g, int d) { int i; for (i = 0; i < BIG.DNLEN; i++) { w[i] ^= (w[i] ^ g.w[i]) & BIG.CastToChunk(-d); } }
/* convert to Montgomery n-residue form */ public void nres() { if (ROM.MODTYPE != ROM.PSEUDO_MERSENNE) { DBIG d = new DBIG(x); d.shl(ROM.NLEN * ROM.BASEBITS); x.copy(d.mod(p)); } }
/* this*=c and catch overflow in DBIG */ public virtual DBIG pxmul(int c) { DBIG m = new DBIG(0); long carry = 0; for (int j = 0; j < ROM.NLEN; j++) { carry = m.muladd(w[j], (long)c, carry, j); } m.w[ROM.NLEN] = carry; return(m); }
/* this*=b mod Modulus */ public void Mul(FP b) { if ((long)XES * b.XES > (long)FEXCESS) { Reduce(); } DBIG d = BIG.Mul(x, b.x); x.Copy(Mod(d)); XES = 2; }
/* Galbraith & Scott Method */ public static BIG[] GS(BIG e) { BIG[] u = new BIG[4]; if (ECP.CURVE_PAIRING_TYPE == ECP.BN) { int i, j; BIG t = new BIG(0); BIG q = new BIG(ROM.CURVE_Order); BIG[] v = new BIG[4]; for (i = 0; i < 4; i++) { t.Copy(new BIG(ROM.CURVE_WB[i])); DBIG d = BIG.Mul(t, e); v[i] = new BIG(d.Div(q)); u[i] = new BIG(0); } u[0].Copy(e); for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { t.Copy(new BIG(ROM.CURVE_BB[j][i])); t.Copy(BIG.ModMul(v[j], t, q)); u[i].Add(q); u[i].Sub(t); u[i].Mod(q); } } } else { BIG q = new BIG(ROM.CURVE_Order); BIG x = new BIG(ROM.CURVE_Bnx); BIG w = new BIG(e); for (int i = 0; i < 3; i++) { u[i] = new BIG(w); u[i].Mod(x); w.Div(x); } u[3] = new BIG(w); if (ECP.SIGN_OF_X == ECP.NEGATIVEX) { u[1].Copy(BIG.ModNeg(u[1], q)); u[3].Copy(BIG.ModNeg(u[3], q)); } } return(u); }
/* convert to Montgomery n-residue form */ public void NRes() { if (MODTYPE != PSEUDO_MERSENNE && MODTYPE != GENERALISED_MERSENNE) { DBIG d = BIG.Mul(x, new BIG(ROM.R2modp)); //** Change ** x.Copy(Mod(d)); XES = 2; } else { XES = 1; } }
/* convert back to regular form */ public BIG Redc() { if (MODTYPE != PSEUDO_MERSENNE && MODTYPE != GENERALISED_MERSENNE) { DBIG d = new DBIG(x); return(Mod(d)); } else { BIG r = new BIG(x); return(r); } }
/* convert back to regular form */ public BIG redc() { if (ROM.MODTYPE != ROM.PSEUDO_MERSENNE) { DBIG d = new DBIG(x); return(BIG.mod(d)); } else { BIG r = new BIG(x); return(r); } }
/* this*=c mod Modulus, where c is a small int */ public void IMul(int c) { // norm(); bool s = false; if (c < 0) { c = -c; s = true; } if (MODTYPE == PSEUDO_MERSENNE || MODTYPE == GENERALISED_MERSENNE) { DBIG d = x.PXMul(c); x.Copy(Mod(d)); XES = 2; } else { if (XES * c <= FEXCESS) { x.PMul(c); XES *= c; } else { // this is not good FP n = new FP(c); Mul(n); } } /* * if (c<=BIG.NEXCESS && XES*c<=FEXCESS) * { * x.imul(c); * XES*=c; * x.norm(); * } * else * { * DBIG d=x.pxmul(c); * x.copy(mod(d)); * XES=2; * } */ if (s) { Neg(); Norm(); } }
/* this*=b mod Modulus */ public void mul(FP b) { long ea = BIG.EXCESS(x); long eb = BIG.EXCESS(b.x); if ((ea + 1) * (eb + 1) + 1 >= ROM.FEXCESS) { reduce(); } DBIG d = BIG.mul(x, b.x); x.copy(BIG.mod(d)); }
/* GLV method */ public static BIG[] Glv(BIG e) { BIG[] u = new BIG[2]; if (ECP.CURVE_PAIRING_TYPE == ECP.BN) { int i, j; BIG t = new BIG(0); BIG q = new BIG(ROM.CURVE_Order); BIG[] v = new BIG[2]; for (i = 0; i < 2; i++) { t.Copy(new BIG(ROM.CURVE_W[i])); // why not just t=new BIG(ROM.CURVE_W[i]); DBIG d = BIG.Mul(t, e); v[i] = new BIG(d.Div(q)); u[i] = new BIG(0); } u[0].Copy(e); for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { t.Copy(new BIG(ROM.CURVE_SB[j][i])); t.Copy(BIG.ModMul(v[j], t, q)); u[i].Add(q); u[i].Sub(t); u[i].Mod(q); } } } else { // -(x^2).P = (Beta.x,y) BIG q = new BIG(ROM.CURVE_Order); BIG x = new BIG(ROM.CURVE_Bnx); BIG x2 = BIG.SMul(x, x); u[0] = new BIG(e); u[0].Mod(x2); u[1] = new BIG(e); u[1].Div(x2); u[1].RSub(q); } return(u); }
/* this*=y */ /* Now uses Lazy reduction */ public void Mul(FP2 y) { if ((long)(a.XES + b.XES) * (y.a.XES + y.b.XES) > (long)FP.FEXCESS) { if (a.XES > 1) { a.Reduce(); } if (b.XES > 1) { b.Reduce(); } } DBIG pR = new DBIG(0); BIG C = new BIG(a.x); BIG D = new BIG(y.a.x); pR.UCopy(new BIG(ROM.Modulus)); DBIG A = BIG.Mul(a.x, y.a.x); DBIG B = BIG.Mul(b.x, y.b.x); C.Add(b.x); C.Norm(); D.Add(y.b.x); D.Norm(); DBIG E = BIG.Mul(C, D); DBIG F = new DBIG(A); F.Add(B); B.RSub(pR); A.Add(B); A.Norm(); E.Sub(F); E.Norm(); a.x.Copy(FP.Mod(A)); a.XES = 3; b.x.Copy(FP.Mod(E)); b.XES = 2; }
/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */ public static int comp(DBIG a, DBIG b) { for (int i = ROM.DNLEN - 1; i >= 0; i--) { if (a.w[i] == b.w[i]) { continue; } if (a.w[i] > b.w[i]) { return(1); } else { return(-1); } } return(0); }
private void karsqr(int vp, FF x, int xp, FF t, int tp, int n) { int nd2; if (n == 1) { DBIG d = BIG.sqr(x.v[xp]); v[vp + 1].copy(d.Split(8 * ROM.MODBYTES)); v[vp].copy(d); return; } nd2 = n / 2; karsqr(vp, x, xp, t, tp + n, nd2); karsqr(vp + n, x, xp + nd2, t, tp + n, nd2); t.karmul(tp, x, xp, x, xp + nd2, t, tp + n, nd2); rinc(vp + nd2, t, tp, n); rinc(vp + nd2, t, tp, n); rnorm(vp + nd2, n); }
/* return a*b as DBIG */ public static DBIG mul(BIG a, BIG b) { DBIG c = new DBIG(0); long carry; a.norm(); b.norm(); for (int i = 0; i < ROM.NLEN; i++) { carry = 0; for (int j = 0; j < ROM.NLEN; j++) { carry = c.muladd(a.w[i], b.w[j], carry, i + j); } c.w[ROM.NLEN + i] = carry; } return(c); }