// x = x/R mod m (HAC 14.32) public void reduce(BigInteger x) { if (x == null) { return; } while (x.t <= this.mt2) { // pad x so am has enough room later x.SetData(x.t++, 0); } for (int i = 0; i < this.m.t; ++i) { // faster way of calculating u0 = x[i]*mp mod DV int j = x.datas[i] & 0x7fff; int u0 = (j * this.mpl + (((j * this.mph + (x.datas[i] >> 15) * this.mpl) & this.um) << 15)) & x.DM; // use am to combine the multiply-shift-add into one call j = i + this.m.t; x.datas[j] += this.m.am(0, u0, x.datas, i, 0, this.m.t); // propagate carry while (x.datas[j] >= x.DV) { x.datas[j] -= x.DV; x.datas[++j]++; } } x.clamp(); x.drShiftTo(this.m.t, x); if (x.compareTo(this.m) >= 0) { x.subTo(this.m, x); } }
public void reduce(BigInteger x) { if (x == null) { return; } x.divRemTo(this.m, null, x); }
public void sqrTo(BigInteger x, BigInteger r) { if (x == null) { return; } x.squareTo(r); this.reduce(r); }
// r = "xy/R mod m"; x,y != r public void mulTo(BigInteger x, BigInteger y, BigInteger r) { if (x == null) { return; } x.multiplyTo(y, r); this.reduce(r); }
public BigInteger convert(BigInteger x) { if (x.s < 0 || x.compareTo(this.m) >= 0) { return x.mod(this.m); } else { return x; } }
// Set the public key fields N and e from hex strings public void setPublic(string N, string E) { if (N != null && E != null && N.Length > 0 && E.Length > 0) { this.n = parseBigInt(N, 16); this.e = int.Parse(E, NumberStyles.HexNumber); } else { //alert("Invalid RSA public key"); } }
public RSAKey() { this.n = null; this.e = 0; /* this.d = null; this.p = null; this.q = null; this.dmp1 = null; this.dmq1 = null; this.coeff = null; */ }
public Montgomery(BigInteger m) { if (m == null) { return; } this.m = m; this.mp = m.invDigit(); this.mpl = this.mp & 0x7fff; this.mph = this.mp >> 15; this.um = (1 << (m.DB - 15)) - 1; this.mt2 = 2 * m.t; }
// xR mod m public BigInteger convert(BigInteger x) { if (x == null) { return null; } BigInteger r = new BigInteger(); x.abs().dlShiftTo(this.m.t, r); r.divRemTo(this.m, null, r); if (x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) { this.m.subTo(r, r); } return r; }
public BigInteger revert(BigInteger x) { return x; }
// (protected) r = this << n public void lShiftTo(int n, BigInteger r) { if (r == null) { r = new BigInteger(); } int bs = n % this.DB; int cbs = this.DB - bs; int bm = (1 << cbs) - 1; int ds = n / this.DB; int c = (this.s << bs) & this.DM; int i; for (i = this.t - 1; i >= 0; --i) { r.SetData(i + ds + 1, (this.datas[i] >> cbs) | c); c = (this.datas[i] & bm) << bs; } for (i = ds - 1; i >= 0; --i) { r.SetData(i, 0); } r.SetData(ds, c); r.t = this.t + ds + 1; r.s = this.s; r.clamp(); }
// (protected) r = this - a public void subTo(BigInteger a, BigInteger r) { if (a == null) { return; } if (r == null) { r = new BigInteger(); } int i = 0, c = 0, m = Math.Min(a.t, this.t); while (i < m) { c += this.datas[i] - a.datas[i]; r.SetData(i++, c & this.DM); c >>= this.DB; } if (a.t < this.t) { c -= a.s; while (i < this.t) { c += this.datas[i]; r.SetData(i++, c & this.DM); c >>= this.DB; } c += this.s; } else { c += this.s; while (i < a.t) { c -= a.datas[i]; r.SetData(i++, c & this.DM); c >>= this.DB; } c -= a.s; } r.s = (c < 0) ? -1 : 0; if (c < -1) { r.SetData(i++, this.DV + c); } else if (c > 0) { r.SetData(i++, c); } r.t = i; r.clamp(); }
// x/R mod m public BigInteger revert(BigInteger x) { BigInteger r = new BigInteger(); x.copyTo(r); this.reduce(r); return r; }
// (protected) r = this >> n public void rShiftTo(int n, BigInteger r) { if (r == null) { r = new BigInteger(); } r.s = this.s; int ds = n / this.DB; if (ds >= this.t) { r.t = 0; return; } int bs = n % this.DB; int cbs = this.DB - bs; int bm = (1 << bs) - 1; r.SetData(0, this.datas[ds] >> bs); for (int i = ds + 1; i < this.t; ++i) { r.datas[i - ds - 1] |= (this.datas[i] & bm) << cbs; r.SetData(i - ds, this.datas[i] >> bs); } if (bs > 0) { r.datas[this.t - ds - 1] |= (this.s & bm) << cbs; } r.t = this.t - ds; r.clamp(); }
// (protected) r = this^2, r != this (HAC 14.16) public void squareTo(BigInteger r) { if (r == null) { r = new BigInteger(); } BigInteger x = this.abs(); int i = r.t = 2 * x.t; while (--i >= 0) { r.SetData(i, 0); } for (i = 0; i < x.t - 1; ++i) { int c = x.am(i, x.datas[i], r.datas, 2 * i, 0, 1); r.datas[i + x.t] += x.am(i + 1, 2 * x.datas[i], r.datas, 2 * i + 1, c, x.t - i - 1); if (r.datas[i + x.t] >= x.DV) { r.datas[i + x.t] -= x.DV; r.datas[i + x.t + 1] = 1; } } if (r.t > 0) { r.datas[r.t - 1] += x.am(i, x.datas[i], r.datas, 2 * i, 0, 1); } r.s = 0; r.clamp(); }
// (public) return + if this > a, - if this < a, 0 if equal public int compareTo(BigInteger a) { if (a == null) { return 1; } int r = this.s - a.s; if (r != 0) { return r; } int i = this.t; r = i - a.t; if (r != 0) { return r; } while (--i >= 0) { if ((r = this.datas[i] - a.datas[i]) != 0) { return r; } } return 0; }
// (public) -this public BigInteger negate() { BigInteger r = new BigInteger(); ZERO.subTo(this, r); return r; }
// (protected) copy this to r public void copyTo(BigInteger r) { if (r == null) { r = new BigInteger(); } for (int i = 0; i < this.t; i++) { r.SetData(i, this.datas[i]); } r.t = this.t; r.s = this.s; }
// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) // r != q, this != m. q or r may be null. public void divRemTo(BigInteger m, BigInteger q, BigInteger r) { if (m == null) { return; } if (q == null) { q = new BigInteger(); } if (r == null) { r = new BigInteger(); } BigInteger pm = m.abs(); if (pm.t <= 0) { return; } BigInteger pt = this.abs(); if (pt.t < pm.t) { if (q != null) { q.fromInt(0); } if (r != null) { this.copyTo(r); } return; } BigInteger y = new BigInteger(); int ts = this.s, ms = m.s; int nsh = this.DB - nbits(pm.datas[pm.t - 1]); // normalize modulus if (nsh > 0) { pm.lShiftTo(nsh, y); pt.lShiftTo(nsh, r); } else { pm.copyTo(y); pt.copyTo(r); } int ys = y.t; int y0 = y.datas[ys - 1]; if (y0 == 0) { return; } long yt = (long)y0 * (1 << this.F1) + ((ys > 1) ? y.datas[ys - 2] >> this.F2 : 0); double d1 = (double)this.FV / yt; double d2 = (double)((long)1 << this.F1) / yt; int e = 1 << this.F2; int i = r.t, j = i - ys; BigInteger t = (q == null) ? new BigInteger() : q; y.dlShiftTo(j, t); if (r.compareTo(t) >= 0) { r.SetData(r.t++, 1); r.subTo(t, r); } ONE.dlShiftTo(ys, t); t.subTo(y, y); // "negative" y so we can replace sub with am later while (y.t < ys) { y.SetData(y.t++, 0); } while (--j >= 0) { // Estimate quotient digit int qd = (r.datas[--i] == y0) ? this.DM : Convert.ToInt32(Math.Floor((double)r.datas[i] * d1 + (double)(r.datas[i - 1] + e) * d2)); int tmp = y.am(0, qd, r.datas, j, 0, ys); if ((r.datas[i] += tmp) < qd) { // Try it out y.dlShiftTo(j, t); r.subTo(t, r); while (r.datas[i] < --qd) { r.subTo(t, r); } } } if (q != null) { r.drShiftTo(ys, q); if (ts != ms) { ZERO.subTo(q, q); } } r.t = ys; r.clamp(); if (nsh > 0) { r.rShiftTo(nsh, r); // Denormalize remainder } if (ts < 0) { ZERO.subTo(r, r); } }
// (protected) r = this << n*DB public void dlShiftTo(int n, BigInteger r) { if (r == null) { r = new BigInteger(); } int i; for (i = this.t - 1; i >= 0; --i) { r.SetData(i + n, this.datas[i]); } for (i = n - 1; i >= 0; --i) { r.SetData(i, 0); } r.t = this.t + n; r.s = this.s; }
// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) public BigInteger exp(int e, Montgomery z) { if (e > 0x7fffffff || e < 1) { return ONE; } BigInteger r = new BigInteger(), r2 = new BigInteger(); BigInteger g = z.convert(this); int i = nbits(e) - 1; g.copyTo(r); while (--i >= 0) { z.sqrTo(r, r2); if ((e & (1 << i)) > 0) { z.mulTo(r2, g, r); } else { BigInteger t = r; r = r2; r2 = t; } } return z.revert(r); }
// (protected) r = this >> n*DB public void drShiftTo(int n, BigInteger r) { if (r == null) { r = new BigInteger(); } for (int i = n; i < this.t; ++i) { r.SetData(i - n, this.datas[i]); } r.t = Math.Max(this.t - n, 0); r.s = this.s; }
// (public) this mod a public BigInteger mod(BigInteger a) { BigInteger r = new BigInteger(); this.abs().divRemTo(a, null, r); if (this.s < 0 && r.compareTo(ZERO) > 0) { a.subTo(r, r); } return r; }
// (public) this^e % m, 0 <= e < 2^32 public BigInteger modPowInt(int e, BigInteger m) { BigInteger r = new BigInteger(); if (e < 256 || m.isEven()) { Classic z = new Classic(m); r = this.exp(e, z); } else { Montgomery z = new Montgomery(m); r = this.exp(e, z); } return r; }
// convert a (hex) string to a bignum object public BigInteger parseBigInt(string str, int r) { BigInteger bint = new BigInteger(str, r); return bint; }
// (protected) r = this * a, r != this,a (HAC 14.12) // "this" should be the larger one if appropriate. public void multiplyTo(BigInteger a, BigInteger r) { if (a == null) { return; } if (r == null) { r = new BigInteger(); } BigInteger x = this.abs(), y = a.abs(); int i = x.t; r.t = i + y.t; while (--i >= 0) { r.SetData(i, 0); } for (i = 0; i < y.t; ++i) { r.datas[i + x.t] = x.am(0, y.datas[i], r.datas, i, 0, x.t); } r.s = 0; r.clamp(); if (this.s != a.s) { ZERO.subTo(r, r); } }
// Perform raw public operation on "x": return x^e (mod n) private BigInteger doPublic(BigInteger x) { return x.modPowInt(this.e, this.n); }
public Classic(BigInteger m) { this.m = m; }