caesar
Version:
An easy-to-use advanced cryptography library.
331 lines (317 loc) • 8.82 kB
JavaScript
// 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);