/* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */ public void skpow(BIG e, FF p) { int i, b, n = p.length; FF R0 = new FF(n); FF R1 = new FF(n); FF ND = p.invmod2m(); mod(p); R0.one(); R1.copy(this); R0.nres(p); R1.nres(p); for (i = 8 * ROM.MODBYTES - 1; i >= 0; i--) { b = e.bit(i); copy(R0); modmul(R1, p, ND); cswap(R0, R1, b); R0.modsqr(p, ND); R1.copy(this); cswap(R0, R1, b); } copy(R0); redc(p, ND); }
/* double exponentiation r=x^e.y^f mod p */ public void pow2(BIG e, FF y, BIG f, FF p) { int i, eb, fb, n = p.length; FF xn = new FF(n); FF yn = new FF(n); FF xy = new FF(n); FF ND = p.invmod2m(); xn.copy(this); yn.copy(y); xn.nres(p); yn.nres(p); xy.copy(xn); xy.modmul(yn, p, ND); one(); nres(p); for (i = 8 * ROM.MODBYTES - 1; i >= 0; i--) { eb = e.bit(i); fb = f.bit(i); modsqr(p, ND); if (eb == 1) { if (fb == 1) { modmul(xy, p, ND); } else { modmul(xn, p, ND); } } else { if (fb == 1) { modmul(yn, p, ND); } } } redc(p, ND); }
/* raise to an integer power - right-to-left method */ public void power(int e, FF p) { int n = p.length; FF w = new FF(n); FF ND = p.invmod2m(); bool f = true; w.copy(this); w.nres(p); if (e == 2) { copy(w); modsqr(p, ND); } else { for (; ;) { if (e % 2 == 1) { if (f) { copy(w); } else { modmul(w, p, ND); } f = false; } e >>= 1; if (e == 0) { break; } w.modsqr(p, ND); } } redc(p, ND); }
/* this=this^e mod p, faster but not side channel resistant */ public void pow(FF e, FF p) { int i, b, n = p.length; FF w = new FF(n); FF ND = p.invmod2m(); w.copy(this); one(); nres(p); w.nres(p); for (i = 8 * ROM.MODBYTES * n - 1; i >= 0; i--) { modsqr(p, ND); b = e.v[i / 256].bit(i % 256); if (b == 1) { modmul(w, p, ND); } } redc(p, ND); }