/* return this^e mod Modulus * public FP pow(BIG e) * { * int bt; * FP r=new FP(1); * e.norm(); * x.norm(); * FP m=new FP(this); * while (true) * { * bt=e.parity(); * e.fshr(1); * if (bt==1) r.mul(m); * if (e.iszilch()) break; * m.sqr(); * } * r.x.mod(p); * return r; * } */ /* return sqrt(this) mod Modulus */ public FP Sqrt() { Reduce(); BIG b = new BIG(ROM.Modulus); if (MOD8 == 5) { b.Dec(5); b.Norm(); b.Shr(3); FP i = new FP(this); i.x.Shl(1); FP v = i.Pow(b); i.Mul(v); i.Mul(v); i.x.Dec(1); FP r = new FP(this); r.Mul(v); r.Mul(i); r.Reduce(); return(r); } else { b.Inc(1); b.Norm(); b.Shr(2); return(Pow(b)); } }
/* this=this^e */ public FP4 Pow(BIG e) { Norm(); e.Norm(); FP4 w = new FP4(this); BIG z = new BIG(e); FP4 r = new FP4(1); while (true) { int bt = z.Parity(); z.FShr(1); if (bt == 1) { r.Mul(w); } if (z.IsZilch()) { break; } w.Sqr(); } r.Reduce(); return(r); }
/* r=x^n using XTR method on traces of FP12s */ public FP4 Xtr_Pow(BIG n) { FP4 a = new FP4(3); FP4 b = new FP4(this); FP4 c = new FP4(b); c.Xtr_D(); FP4 t = new FP4(0); FP4 r = new FP4(0); n.Norm(); int par = n.Parity(); BIG v = new BIG(n); v.FShr(1); if (par == 0) { v.Dec(1); v.Norm(); } int nb = v.NBits(); for (int i = nb - 1; i >= 0; i--) { if (v.Bit(i) != 1) { t.Copy(b); Conj(); c.Conj(); b.Xtr_A(a, this, c); Conj(); c.Copy(t); c.Xtr_D(); a.Xtr_D(); } else { t.Copy(a); t.Conj(); a.Copy(b); a.Xtr_D(); b.Xtr_A(c, this, t); c.Xtr_D(); } } if (par == 0) { r.Copy(c); } else { r.Copy(b); } r.Reduce(); return(r); }
/* this=1/this mod Modulus */ public void Inverse() { /* * BIG r=redc(); * r.invmodp(p); * x.copy(r); * nres(); */ BIG m2 = new BIG(ROM.Modulus); m2.Dec(2); m2.Norm(); Copy(Pow(m2)); }
public FP Pow(BIG e) { sbyte[] w = new sbyte[1 + (BIG.NLEN * BIG.BASEBITS + 3) / 4]; FP[] tb = new FP[16]; BIG t = new BIG(e); t.Norm(); int nb = 1 + (t.NBits() + 3) / 4; for (int i = 0; i < nb; i++) { int lsbs = t.LastBits(4); t.Dec(lsbs); t.Norm(); w[i] = (sbyte)lsbs; t.FShr(4); } tb[0] = new FP(1); tb[1] = new FP(this); for (int i = 2; i < 16; i++) { tb[i] = new FP(tb[i - 1]); tb[i].Mul(this); } FP r = new FP(tb[w[nb - 1]]); for (int i = nb - 2; i >= 0; i--) { r.Sqr(); r.Sqr(); r.Sqr(); r.Sqr(); r.Mul(tb[w[i]]); } r.Reduce(); return(r); }
/* this=this^e */ /* Note this is simple square and multiply, so not side-channel safe */ public FP12 Pow(BIG e) { Norm(); e.Norm(); BIG e3 = new BIG(e); e3.PMul(3); e3.Norm(); FP12 w = new FP12(this); int nb = e3.NBits(); for (int i = nb - 2; i >= 1; i--) { w.USqr(); int bt = e3.Bit(i) - e.Bit(i); if (bt == 1) { w.mul(this); } if (bt == -1) { Conj(); w.mul(this); Conj(); } } w.Reduce(); return(w); /* * BIG z=new BIG(e); * FP12 r=new FP12(1); * * while (true) * { * int bt=z.parity(); * z.fshr(1); * if (bt==1) r.mul(w); * if (z.iszilch()) break; * w.usqr(); * } * r.reduce(); * return r; */ }
/* 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; }
/* return this/c */ public virtual BIG Div(BIG c) { int d, k = 0; DBIG m = new DBIG(c); DBIG dr = new DBIG(0); BIG r = new BIG(0); 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); dr.Copy(this); dr.Sub(m); dr.Norm(); d = (int)(1 - ((dr.w[BIG.DNLEN - 1] >> (BIG.CHUNK - 1)) & 1)); CMove(dr, d); r.Copy(a); r.Add(e); r.Norm(); a.CMove(r, d); k--; } return(a); }
/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */ public FP4 Xtr_Pow2(FP4 ck, FP4 ckml, FP4 ckm2l, BIG a, BIG b) { a.Norm(); b.Norm(); BIG e = new BIG(a); BIG d = new BIG(b); BIG w = new BIG(0); FP4 cu = new FP4(ck); // can probably be passed in w/o copying FP4 cv = new FP4(this); FP4 cumv = new FP4(ckml); FP4 cum2v = new FP4(ckm2l); FP4 r = new FP4(0); FP4 t = new FP4(0); int f2 = 0; while (d.Parity() == 0 && e.Parity() == 0) { d.FShr(1); e.FShr(1); f2++; } while (BIG.Comp(d, e) != 0) { if (BIG.Comp(d, e) > 0) { w.Copy(e); w.IMul(4); w.Norm(); if (BIG.Comp(d, w) <= 0) { w.Copy(d); d.Copy(e); e.RSub(w); e.Norm(); t.Copy(cv); t.Xtr_A(cu, cumv, cum2v); cum2v.Copy(cumv); cum2v.Conj(); cumv.Copy(cv); cv.Copy(cu); cu.Copy(t); } else if (d.Parity() == 0) { d.FShr(1); r.Copy(cum2v); r.Conj(); t.Copy(cumv); t.Xtr_A(cu, cv, r); cum2v.Copy(cumv); cum2v.Xtr_D(); cumv.Copy(t); cu.Xtr_D(); } else if (e.Parity() == 1) { d.Sub(e); d.Norm(); d.FShr(1); t.Copy(cv); t.Xtr_A(cu, cumv, cum2v); cu.Xtr_D(); cum2v.Copy(cv); cum2v.Xtr_D(); cum2v.Conj(); cv.Copy(t); } else { w.Copy(d); d.Copy(e); d.FShr(1); e.Copy(w); t.Copy(cumv); t.Xtr_D(); cumv.Copy(cum2v); cumv.Conj(); cum2v.Copy(t); cum2v.Conj(); t.Copy(cv); t.Xtr_D(); cv.Copy(cu); cu.Copy(t); } } if (BIG.Comp(d, e) < 0) { w.Copy(d); w.IMul(4); w.Norm(); if (BIG.Comp(e, w) <= 0) { e.Sub(d); e.Norm(); t.Copy(cv); t.Xtr_A(cu, cumv, cum2v); cum2v.Copy(cumv); cumv.Copy(cu); cu.Copy(t); } else if (e.Parity() == 0) { w.Copy(d); d.Copy(e); d.FShr(1); e.Copy(w); t.Copy(cumv); t.Xtr_D(); cumv.Copy(cum2v); cumv.Conj(); cum2v.Copy(t); cum2v.Conj(); t.Copy(cv); t.Xtr_D(); cv.Copy(cu); cu.Copy(t); } else if (d.Parity() == 1) { w.Copy(e); e.Copy(d); w.Sub(d); w.Norm(); d.Copy(w); d.FShr(1); t.Copy(cv); t.Xtr_A(cu, cumv, cum2v); cumv.Conj(); cum2v.Copy(cu); cum2v.Xtr_D(); cum2v.Conj(); cu.Copy(cv); cu.Xtr_D(); cv.Copy(t); } else { d.FShr(1); r.Copy(cum2v); r.Conj(); t.Copy(cumv); t.Xtr_A(cu, cv, r); cum2v.Copy(cumv); cum2v.Xtr_D(); cumv.Copy(t); cu.Xtr_D(); } } } r.Copy(cv); r.Xtr_A(cu, cumv, cum2v); for (int i = 0; i < f2; i++) { r.Xtr_D(); } r = r.Xtr_Pow(d); return(r); }
/* Optimal R-ate double pairing e(P,Q).e(R,S) */ public static FP12 Ate2(ECP2 P1, ECP Q1, ECP2 R1, ECP S1) { FP2 f; BIG x = new BIG(ROM.CURVE_Bnx); BIG n = new BIG(x); ECP2 K = new ECP2(); FP12 lv; int bt; ECP2 P = new ECP2(P1); ECP Q = new ECP(Q1); P.Affine(); Q.Affine(); ECP2 R = new ECP2(R1); ECP S = new ECP(S1); R.Affine(); S.Affine(); if (ECP.CURVE_PAIRING_TYPE == ECP.BN) { f = new FP2(new BIG(ROM.Fra), new BIG(ROM.Frb)); if (ECP.SEXTIC_TWIST == ECP.M_TYPE) { f.Inverse(); f.Norm(); } n.PMul(6); if (ECP.SIGN_OF_X == ECP.POSITIVEX) { n.Inc(2); } else { n.Dec(2); } } else { n.Copy(x); } n.Norm(); BIG n3 = new BIG(n); n3.PMul(3); n3.Norm(); FP Qx = new FP(Q.GetX()); FP Qy = new FP(Q.GetY()); FP Sx = new FP(S.GetX()); FP Sy = new FP(S.GetY()); ECP2 A = new ECP2(); ECP2 B = new ECP2(); FP12 r = new FP12(1); A.Copy(P); B.Copy(R); ECP2 MP = new ECP2(); MP.Copy(P); MP.Neg(); ECP2 MR = new ECP2(); MR.Copy(R); MR.Neg(); int nb = n3.NBits(); for (int i = nb - 2; i >= 1; i--) { r.Sqr(); lv = Line(A, A, Qx, Qy); r.SMul(lv, ECP.SEXTIC_TWIST); lv = Line(B, B, Sx, Sy); r.SMul(lv, ECP.SEXTIC_TWIST); bt = n3.Bit(i) - n.Bit(i); // bt=n.bit(i); if (bt == 1) { lv = Line(A, P, Qx, Qy); r.SMul(lv, ECP.SEXTIC_TWIST); lv = Line(B, R, Sx, Sy); r.SMul(lv, ECP.SEXTIC_TWIST); } if (bt == -1) { //P.neg(); lv = Line(A, MP, Qx, Qy); r.SMul(lv, ECP.SEXTIC_TWIST); //P.neg(); //R.neg(); lv = Line(B, MR, Sx, Sy); r.SMul(lv, ECP.SEXTIC_TWIST); //R.neg(); } } if (ECP.SIGN_OF_X == ECP.NEGATIVEX) { r.Conj(); } /* R-ate fixup required for BN curves */ if (ECP.CURVE_PAIRING_TYPE == ECP.BN) { if (ECP.SIGN_OF_X == ECP.NEGATIVEX) { // r.conj(); A.Neg(); B.Neg(); } K.Copy(P); K.Frob(f); lv = Line(A, K, Qx, Qy); r.SMul(lv, ECP.SEXTIC_TWIST); K.Frob(f); K.Neg(); lv = Line(A, K, Qx, Qy); r.SMul(lv, ECP.SEXTIC_TWIST); K.Copy(R); K.Frob(f); lv = Line(B, K, Sx, Sy); r.SMul(lv, ECP.SEXTIC_TWIST); K.Frob(f); K.Neg(); lv = Line(B, K, Sx, Sy); r.SMul(lv, ECP.SEXTIC_TWIST); } return(r); }
/// <summary> ///************** 64-bit specific *********************** </summary> /* reduce a DBIG to a BIG using the appropriate form of the modulus */ public static BIG Mod(DBIG d) { if (MODTYPE == PSEUDO_MERSENNE) { BIG b; long v, tw; BIG t = d.Split(MODBITS); b = new BIG(d); v = t.PMul(unchecked ((int)ROM.MConst)); t.Add(b); t.Norm(); tw = t.w[BIG.NLEN - 1]; t.w[BIG.NLEN - 1] &= FP.TMASK; t.w[0] += (ROM.MConst * ((tw >> TBITS) + (v << (BIG.BASEBITS - TBITS)))); t.Norm(); return(t); } if (FP.MODTYPE == MONTGOMERY_FRIENDLY) { BIG b; long[] cr = new long[2]; for (int i = 0; i < BIG.NLEN; i++) { cr = BIG.MulAdd(d.w[i], ROM.MConst - 1, d.w[i], d.w[BIG.NLEN + i - 1]); d.w[BIG.NLEN + i] += cr[0]; d.w[BIG.NLEN + i - 1] = cr[1]; } b = new BIG(0); for (int i = 0; i < BIG.NLEN; i++) { b.w[i] = d.w[BIG.NLEN + i]; } b.Norm(); return(b); } if (MODTYPE == GENERALISED_MERSENNE) { // GoldiLocks Only BIG b; BIG t = d.Split(MODBITS); b = new BIG(d); b.Add(t); DBIG dd = new DBIG(t); dd.Shl(MODBITS / 2); BIG tt = dd.Split(MODBITS); BIG lo = new BIG(dd); b.Add(tt); b.Add(lo); b.Norm(); tt.Shl(MODBITS / 2); b.Add(tt); long carry = b.w[BIG.NLEN - 1] >> TBITS; b.w[BIG.NLEN - 1] &= FP.TMASK; b.w[0] += carry; b.w[224 / BIG.BASEBITS] += carry << (224 % BIG.BASEBITS); b.Norm(); return(b); } if (MODTYPE == NOT_SPECIAL) { return(BIG.Monty(new BIG(ROM.Modulus), ROM.MConst, d)); } return(new BIG(0)); }
/* normalise this */ public void Norm() { x.Norm(); }