UNPKG

caesar

Version:

An easy-to-use advanced cryptography library.

331 lines (317 loc) 8.82 kB
// Generated by CoffeeScript 1.7.1 (function() { var BigDecimal, BigInteger, PRNG, afc, crypto, imax2, imin2, rhyper; crypto = require('crypto'); BigDecimal = require('bigdecimal').BigDecimal; BigInteger = require('bigdecimal').BigInteger; exports.encrypt = function(key, num) { var bcursor, bottom, cursor, k, ocursor, okay, top; top = 131072; cursor = 65536; bottom = 0; while (true) { k = rhyper(key, 65536, 65536, cursor); if (Math.abs(num - k) < 20) { break; } if (num > k) { bottom = cursor; } if (num < k) { top = cursor; } if (cursor % 4 === 1) { cursor = Math.floor((top + bottom) / 2); } else if (cursor % 4 === 3) { cursor = Math.ceil((top + bottom) / 2); } else { cursor = (top + bottom) / 2; } } ocursor = cursor + 20; if (k > num) { cursor -= 80; } if (cursor < 0) { cursor = 0; } bcursor = cursor; okay = false; while (!okay && cursor <= ocursor) { cursor = cursor + 2; k = rhyper(key, 65536, 65536, cursor); if (k === num) { okay = true; } } if (!okay) { while (bcursor <= ocursor) { bcursor = bcursor + 2; k = rhyper(key, 65536, 65536, bcursor); if (k > num) { bcursor -= 1; break; } } cursor = bcursor; } return cursor; }; afc = function(i) { var al, pi; al = { 0: '0', 1: '0', 2: '0.69314718055994530941723212145817', 3: '1.79175946922805500081247735838070', 4: '3.17805383034794561964694160129705', 5: '4.78749174278204599424770093452324', 6: '6.57925121201010099506017829290394', 7: '8.52516136106541430016553103634712', 8: '10.60460290274525022841722740072165' }; if (i < 0) { throw 'i less than 0. Should not happen.'; } if (i <= 8) { return al[i]; } pi = 0.5 * Math.log(2 * Math.PI); return (i + 0.5) * Math.log(i) - i + (1 / 12) / i - (1 / 360) / i / i / i + pi; }; imax2 = function(x, y) { if (x < y) { return y; } else { return x; } }; imin2 = function(x, y) { if (x < y) { return x; } else { return y; } }; PRNG = (function() { function PRNG(coin) { this.coin = coin; this.cipher = crypto.createCipher('aes-256-ctr', this.coin); this.blank = new Buffer(16); this.blank.fill(0); } PRNG.prototype.draw = function() { var denom, numer, out; this.cipher.write(this.blank); out = this.cipher.read(); numer = new BigInteger(out.toString('hex'), 16); numer = new BigDecimal(numer.toString()); denom = new BigDecimal('340282366920938463463374607431768211456'); return parseFloat(numer.divide(denom, 100, BigDecimal.ROUND_HALF_UP).toString()); }; return PRNG; })(); rhyper = function(coin, nn1, nn2, kk) { var a, alv, cand, con, d, de, deltal, deltau, dg, dr, ds, dt, e, f, g, gl, gu, i, ix, k, kl, kr, ks, l10, lamdl, lamdr, m, maxjx, minjx, n1, n1s, n2, n2s, nk, nm, p, p1, p2, p3, prng, r, s, scale, setup1, setup2, t, tk, tn, u, ub, v, w, xk, xl, xm, xn, xr, y, y1, yk, ym, yn, _ref, _ref1; prng = new PRNG(coin); con = 57.56462733; deltal = 0.0078; deltau = 0.0034; ks = -1; n1s = -1; n2s = -1; scale = 1e25; if (nn1 === Infinity || nn2 === Infinity || kk === Infinity) { throw 'NaN'; } nn1 = Math.floor(nn1 + 0.5); nn2 = Math.floor(nn2 + 0.5); kk = Math.floor(kk + 0.5); if (nn1 < 0 || nn2 < 0 || kk < 0 || kk > (nn1 + nn2)) { throw 'NaN'; } if (nn1 !== n1s || nn2 !== n2s) { setup1 = true; setup2 = true; } else if (kk !== ks) { setup1 = false; setup2 = true; } else { setup1 = false; setup2 = false; } if (setup1) { n1s = nn1; n2s = nn2; tn = nn1 + nn2; if (nn1 <= nn2) { n1 = nn1; n2 = nn2; } else { n1 = nn2; n2 = nn1; } } if (setup2) { ks = kk; tk = kk + kk; if ((kk + kk) >= tn) { k = tn - kk; } else { k = kk; } } if (setup1 || setup2) { m = (k + 1) * (n1 + 1) / (tn + 2); minjx = imax2(0, k - n2); maxjx = imin2(n1, k); } if (minjx === maxjx) { ix = maxjx; } else if ((m - minjx) < 10) { if (setup1 || setup2) { if (k < n2) { w = Math.exp(con + afc(n2) + afc(n1 + n2 - k) - afc(n2 - k) - afc(n1 + n2)); } else { w = Math.exp(con + afc(n1) + afc(k) - afc(k - n2) - afc(n1 + n2)); } } l10 = function(w, minjx) { var p, u; p = w; ix = minjx; u = prng.draw() * 1e25; return [p, ix, u]; }; _ref = l10(w, minjx), p = _ref[0], ix = _ref[1], u = _ref[2]; while (u > p) { u -= p; p *= (n1 - ix) * (k - ix); ++ix; p = p / ix / (n2 - k + ix); if (ix > maxjx) { _ref1 = l10(w, minjx), p = _ref1[0], ix = _ref1[1], u = _ref1[2]; } } } else { if (setup1 || setup2) { s = Math.sqrt((tn - k) * k * n1 * n2 / (tn - 1) / tn / tn); d = Math.floor((1.5 * s) + 0.5); xl = m - d + 0.5; xr = m + d + 0.5; a = afc(m) + afc(n1 - m) + afc(k - m) + afc(n2 - k + m); kl = Math.exp(a - afc(Math.floor(xl)) - afc(Math.floor(n1 - xl)) - afc(Math.floor(k - xl)) - afc(Math.floor(n2 - k + xl))); kr = Math.exp(a - afc(Math.floor(xr - 1)) - afc(Math.floor(n1 - xr + 1)) - afc(Math.floor(k - xr + 1)) - afc(Math.floor(n2 - k + xr - 1))); lamdl = -Math.log(xl * (n2 - k + xl) / (n1 - xl + 1) / (k - xl + 1)); lamdr = -Math.log((n1 - xr + 1) * (k - xr + 1) / xr / (n2 - k + xr)); p1 = d + d; p2 = p1 + kl / lamdl; p3 = p2 + kr / lamdr; } while (true) { u = prng.draw() * p3; v = prng.draw(); if (u < p1) { ix = Math.floor(xl + u); } else if (u <= p2) { ix = Math.floor(xl + Math.log(v) / lamdl); if (ix < minjx) { continue; } v = v * (u - p1) * lamdl; } else { ix = Math.floor(xr - Math.log(v) / lamdr); if (ix > maxjx) { continue; } v = v * (u - p2) * lamdr; } if (m < 100 || ix <= 50) { f = 1; if (m < ix) { i = m + 1; while (i <= ix) { f = f * (n1 - i + 1) * (k - i + 1) / (n2 - k + i) / i; ++i; } } else if (m > ix) { i = ix + 1; while (i <= m) { f = f * i * (n2 - k + i) / (n1 - i + 1) / (k - i + 1); ++i; } } if (v <= f) { break; } } else { y = ix; y1 = y + 1; ym = y - m; yn = n1 - y + 1; yk = k - y + 1; nk = n2 - k + y1; r = -ym / y1; s = ym / yn; t = ym / yk; e = -ym / nk; g = yn * yk / (y1 * nk) - 1; dg = 1; if (g < 0) { dg = 1 + g; } gu = g * (1 + g * (-0.5 + g / 3)); gl = gu - .25 * (g * g * g * g) / dg; xm = m + 0.5; xn = n1 - m + 0.5; xk = k - m + 0.5; nm = n2 - k + xm; ub = y * gu - m * gl + deltau + xm * r * (1 + r * (-0.5 + r / 3)) + xn * s * (1 + s * (-0.5 + s / 3)) + xk * t * (1 + t * (-0.5 + t / 3)) + nm * e * (1 + e * (-0.5 + e / 3)); alv = Math.log(v); if (alv > ub) { continue; } dr = xm * (r * r * r * r); if (r < 0) { dr /= 1 + r; } ds = xn * (s * s * s * s); if (s < 0) { ds /= 1 + s; } dt = xk * (t * t * t * t); if (t < 0) { dt /= 1 + t; } de = nm * (e * e * e * e); if (e < 0) { de /= 1 + e; } cand = ub - 0.25 * (dr + ds + dt + de) + (y + m) * (gl - gu) - deltal; if (alv < cand) { break; } else { cand = a - afc(ix) - afc(n1 - ix) - afc(k - ix) - afc(n2 - k + ix); if (alv <= cand) { break; } else { continue; } } } } } if ((kk + kk) >= tn) { if (nn1 > nn2) { ix = kk - nn2 + ix; } else { ix = nn1 - ix; } } else { if (nn1 > nn2) { ix = kk - ix; } } return ix; }; }).call(this);