|
@@ -1,17 +1,14 @@
|
|
|
;(function (root, factory) {
|
|
|
|
|
|
- var Salsa20, crypto
|
|
|
if (typeof define === 'function' && define.amd) {
|
|
|
- define(['salsa20'], factory.bind(root, root.crypto))
|
|
|
+ define([], factory.bind(root, root.crypto || root.msCrypto))
|
|
|
} else if (typeof module !== 'undefined' && module.exports) {
|
|
|
- Salsa20 = require('./salsa20.js')
|
|
|
- crypto = require('crypto')
|
|
|
- module.exports = factory(crypto, Salsa20)
|
|
|
+ module.exports = factory(require('crypto'))
|
|
|
} else {
|
|
|
- root.BigInt = factory(root.crypto, root.Salsa20)
|
|
|
+ root.BigInt = factory(root.crypto || root.msCrypto)
|
|
|
}
|
|
|
|
|
|
-}(this, function (crypto, Salsa20) {
|
|
|
+}(this, function (crypto) {
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
// Big Integer Library v. 5.5
|
|
@@ -151,7 +148,7 @@
|
|
|
// void linCombShift_(x,y,b,ys) //do x=x+b*(y<<(ys*bpe)) for bigInts x and y, and integers b and ys
|
|
|
// void mont_(x,y,n,np) //Montgomery multiplication (see comments where the function is defined)
|
|
|
// void multInt_(x,n) //do x=x*n where x is a bigInt and n is an integer.
|
|
|
- // void rightShift_(x,n) //right shift bigInt x by n bits. 0 <= n < bpe. (This never overflows its array).
|
|
|
+ // void rightShift_(x,n) //right shift bigInt x by n bits. (This never overflows its array).
|
|
|
// void squareMod_(x,n) //do x=x*x mod n for bigInts x,n
|
|
|
// void subShift_(x,y,ys) //do x=x-(y<<(ys*bpe)). Negative answers will be 2s complement.
|
|
|
//
|
|
@@ -195,18 +192,18 @@
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//globals
|
|
|
- var bpe = 0 // bits stored per array element
|
|
|
- var mask=0; //AND this with an array element to chop it down to bpe bits
|
|
|
- var radix=mask+1; //equals 2^bpe. A single 1 bit to the left of the last bit of mask.
|
|
|
+
|
|
|
+ // The number of significant bits in the fraction of a JavaScript
|
|
|
+ // floating-point number is 52, independent of platform.
|
|
|
+ // See: https://github.com/arlolra/otr/issues/41
|
|
|
+
|
|
|
+ var bpe = 26; // bits stored per array element
|
|
|
+ var radix = 1 << bpe; // equals 2^bpe
|
|
|
+ var mask = radix - 1; // AND this with an array element to chop it down to bpe bits
|
|
|
|
|
|
//the digits for converting to different bases
|
|
|
var digitsStr='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_=!@#$%^&*()[]{}|;:,.<>/?`~ \\\'\"+-';
|
|
|
|
|
|
- //initialize the global variables
|
|
|
- for (bpe = 0; (1<<(bpe+1)) > (1<<bpe); bpe++); // bpe = number of bits in the mantissa on this platform
|
|
|
- bpe>>=1; // bpe = number of bits in one element of the array representing the bigInt
|
|
|
- mask=(1<<bpe)-1; //AND the mask with an integer to get its bpe least significant bits
|
|
|
- radix=mask+1; //2^bpe. a single 1 bit to the left of the first bit of mask
|
|
|
var one=int2bigInt(1,1,1); //constant used in powMod_()
|
|
|
|
|
|
//the following global variables are scratchpad memory to
|
|
@@ -940,11 +937,13 @@
|
|
|
// q[i-ky]--;
|
|
|
for (;;) {
|
|
|
y2=(ky>1 ? y[ky-2] : 0)*q[i-ky];
|
|
|
- c=y2>>bpe;
|
|
|
+ c=y2;
|
|
|
y2=y2 & mask;
|
|
|
+ c = (c - y2) / radix;
|
|
|
y1=c+q[i-ky]*y[ky-1];
|
|
|
- c=y1>>bpe;
|
|
|
+ c=y1;
|
|
|
y1=y1 & mask;
|
|
|
+ c = (c - y1) / radix;
|
|
|
|
|
|
if (c==r[i] ? y1==r[i-1] ? y2>(i>1 ? r[i-2] : 0) : y1>r[i-1] : c>r[i])
|
|
|
q[i-ky]--;
|
|
@@ -972,11 +971,12 @@
|
|
|
c+=x[i];
|
|
|
b=0;
|
|
|
if (c<0) {
|
|
|
- b=-(c>>bpe);
|
|
|
+ b = c & mask;
|
|
|
+ b = -((c - b) / radix);
|
|
|
c+=b*radix;
|
|
|
}
|
|
|
x[i]=c & mask;
|
|
|
- c=(c>>bpe)-b;
|
|
|
+ c = ((c - x[i]) / radix) - b;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1169,16 +1169,17 @@
|
|
|
c+=x[i];
|
|
|
b=0;
|
|
|
if (c<0) {
|
|
|
- b=-(c>>bpe);
|
|
|
+ b = c & mask;
|
|
|
+ b = -((c - b) / radix);
|
|
|
c+=b*radix;
|
|
|
}
|
|
|
x[i]=c & mask;
|
|
|
- c=(c>>bpe)-b;
|
|
|
+ c = ((c - x[i]) / radix) - b;
|
|
|
if (!c) return; //stop carrying as soon as the carry is zero
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- //right shift bigInt x by n bits. 0 <= n < bpe.
|
|
|
+ //right shift bigInt x by n bits.
|
|
|
function rightShift_(x,n) {
|
|
|
var i;
|
|
|
var k=Math.floor(n/bpe);
|
|
@@ -1235,11 +1236,12 @@
|
|
|
c+=x[i]*n;
|
|
|
b=0;
|
|
|
if (c<0) {
|
|
|
- b=-(c>>bpe);
|
|
|
+ b = c & mask;
|
|
|
+ b = -((c - b) / radix);
|
|
|
c+=b*radix;
|
|
|
}
|
|
|
x[i]=c & mask;
|
|
|
- c=(c>>bpe)-b;
|
|
|
+ c = ((c - x[i]) / radix) - b;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1263,12 +1265,12 @@
|
|
|
for (c=0,i=0;i<k;i++) {
|
|
|
c+=a*x[i]+b*y[i];
|
|
|
x[i]=c & mask;
|
|
|
- c>>=bpe;
|
|
|
+ c = (c - x[i]) / radix;
|
|
|
}
|
|
|
for (i=k;i<kk;i++) {
|
|
|
c+=a*x[i];
|
|
|
x[i]=c & mask;
|
|
|
- c>>=bpe;
|
|
|
+ c = (c - x[i]) / radix;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1281,12 +1283,12 @@
|
|
|
for (c=0,i=ys;i<k;i++) {
|
|
|
c+=x[i]+b*y[i-ys];
|
|
|
x[i]=c & mask;
|
|
|
- c>>=bpe;
|
|
|
+ c = (c - x[i]) / radix;
|
|
|
}
|
|
|
for (i=k;c && i<kk;i++) {
|
|
|
c+=x[i];
|
|
|
x[i]=c & mask;
|
|
|
- c>>=bpe;
|
|
|
+ c = (c - x[i]) / radix;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1299,12 +1301,12 @@
|
|
|
for (c=0,i=ys;i<k;i++) {
|
|
|
c+=x[i]+y[i-ys];
|
|
|
x[i]=c & mask;
|
|
|
- c>>=bpe;
|
|
|
+ c = (c - x[i]) / radix;
|
|
|
}
|
|
|
for (i=k;c && i<kk;i++) {
|
|
|
c+=x[i];
|
|
|
x[i]=c & mask;
|
|
|
- c>>=bpe;
|
|
|
+ c = (c - x[i]) / radix;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1317,12 +1319,12 @@
|
|
|
for (c=0,i=ys;i<k;i++) {
|
|
|
c+=x[i]-y[i-ys];
|
|
|
x[i]=c & mask;
|
|
|
- c>>=bpe;
|
|
|
+ c = (c - x[i]) / radix;
|
|
|
}
|
|
|
for (i=k;c && i<kk;i++) {
|
|
|
c+=x[i];
|
|
|
x[i]=c & mask;
|
|
|
- c>>=bpe;
|
|
|
+ c = (c - x[i]) / radix;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1335,12 +1337,12 @@
|
|
|
for (c=0,i=0;i<k;i++) {
|
|
|
c+=x[i]-y[i];
|
|
|
x[i]=c & mask;
|
|
|
- c>>=bpe;
|
|
|
+ c = (c - x[i]) / radix;
|
|
|
}
|
|
|
for (i=k;c && i<x.length;i++) {
|
|
|
c+=x[i];
|
|
|
x[i]=c & mask;
|
|
|
- c>>=bpe;
|
|
|
+ c = (c - x[i]) / radix;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1352,12 +1354,12 @@
|
|
|
for (c=0,i=0;i<k;i++) {
|
|
|
c+=x[i]+y[i];
|
|
|
x[i]=c & mask;
|
|
|
- c>>=bpe;
|
|
|
+ c = (c - x[i]) / radix;
|
|
|
}
|
|
|
for (i=k;c && i<x.length;i++) {
|
|
|
c+=x[i];
|
|
|
x[i]=c & mask;
|
|
|
- c>>=bpe;
|
|
|
+ c = (c - x[i]) / radix;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1409,11 +1411,11 @@
|
|
|
for (i=0;i<kx;i++) {
|
|
|
c=s0[2*i]+x[i]*x[i];
|
|
|
s0[2*i]=c & mask;
|
|
|
- c>>=bpe;
|
|
|
+ c = (c - s0[2*i]) / radix;
|
|
|
for (j=i+1;j<kx;j++) {
|
|
|
c=s0[i+j]+2*x[i]*x[j]+c;
|
|
|
s0[i+j]=(c & mask);
|
|
|
- c>>=bpe;
|
|
|
+ c = (c - s0[i+j]) / radix;
|
|
|
}
|
|
|
s0[i+kx]=c;
|
|
|
}
|
|
@@ -1497,7 +1499,7 @@
|
|
|
// n is odd
|
|
|
// np = -(n^(-1)) mod radix
|
|
|
function mont_(x,y,n,np) {
|
|
|
- var i,j,c,ui,t,ks;
|
|
|
+ var i,j,c,ui,t,t2,ks;
|
|
|
var kn=n.length;
|
|
|
var ky=y.length;
|
|
|
|
|
@@ -1514,24 +1516,35 @@
|
|
|
for (i=0; i<kn; i++) {
|
|
|
t=sa[0]+x[i]*y[0];
|
|
|
ui=((t & mask) * np) & mask; //the inner "& mask" was needed on Safari (but not MSIE) at one time
|
|
|
- c=(t+ui*n[0]) >> bpe;
|
|
|
+ c=(t+ui*n[0]);
|
|
|
+ c = (c - (c & mask)) / radix;
|
|
|
t=x[i];
|
|
|
|
|
|
//do sa=(sa+x[i]*y+ui*n)/b where b=2**bpe. Loop is unrolled 5-fold for speed
|
|
|
j=1;
|
|
|
- for (;j<ky-4;) { c+=sa[j]+ui*n[j]+t*y[j]; sa[j-1]=c & mask; c>>=bpe; j++;
|
|
|
- c+=sa[j]+ui*n[j]+t*y[j]; sa[j-1]=c & mask; c>>=bpe; j++;
|
|
|
- c+=sa[j]+ui*n[j]+t*y[j]; sa[j-1]=c & mask; c>>=bpe; j++;
|
|
|
- c+=sa[j]+ui*n[j]+t*y[j]; sa[j-1]=c & mask; c>>=bpe; j++;
|
|
|
- c+=sa[j]+ui*n[j]+t*y[j]; sa[j-1]=c & mask; c>>=bpe; j++; }
|
|
|
- for (;j<ky;) { c+=sa[j]+ui*n[j]+t*y[j]; sa[j-1]=c & mask; c>>=bpe; j++; }
|
|
|
- for (;j<kn-4;) { c+=sa[j]+ui*n[j]; sa[j-1]=c & mask; c>>=bpe; j++;
|
|
|
- c+=sa[j]+ui*n[j]; sa[j-1]=c & mask; c>>=bpe; j++;
|
|
|
- c+=sa[j]+ui*n[j]; sa[j-1]=c & mask; c>>=bpe; j++;
|
|
|
- c+=sa[j]+ui*n[j]; sa[j-1]=c & mask; c>>=bpe; j++;
|
|
|
- c+=sa[j]+ui*n[j]; sa[j-1]=c & mask; c>>=bpe; j++; }
|
|
|
- for (;j<kn;) { c+=sa[j]+ui*n[j]; sa[j-1]=c & mask; c>>=bpe; j++; }
|
|
|
- for (;j<ks;) { c+=sa[j]; sa[j-1]=c & mask; c>>=bpe; j++; }
|
|
|
+ for (;j<ky-4;) {
|
|
|
+ c+=sa[j]+ui*n[j]+t*y[j]; t2=sa[j-1]=c & mask; c=(c-t2)/radix; j++;
|
|
|
+ c+=sa[j]+ui*n[j]+t*y[j]; t2=sa[j-1]=c & mask; c=(c-t2)/radix; j++;
|
|
|
+ c+=sa[j]+ui*n[j]+t*y[j]; t2=sa[j-1]=c & mask; c=(c-t2)/radix; j++;
|
|
|
+ c+=sa[j]+ui*n[j]+t*y[j]; t2=sa[j-1]=c & mask; c=(c-t2)/radix; j++;
|
|
|
+ c+=sa[j]+ui*n[j]+t*y[j]; t2=sa[j-1]=c & mask; c=(c-t2)/radix; j++;
|
|
|
+ }
|
|
|
+ for (;j<ky;) {
|
|
|
+ c+=sa[j]+ui*n[j]+t*y[j]; t2=sa[j-1]=c & mask; c=(c-t2)/radix; j++;
|
|
|
+ }
|
|
|
+ for (;j<kn-4;) {
|
|
|
+ c+=sa[j]+ui*n[j]; t2=sa[j-1]=c & mask; c=(c-t2)/radix; j++;
|
|
|
+ c+=sa[j]+ui*n[j]; t2=sa[j-1]=c & mask; c=(c-t2)/radix; j++;
|
|
|
+ c+=sa[j]+ui*n[j]; t2=sa[j-1]=c & mask; c=(c-t2)/radix; j++;
|
|
|
+ c+=sa[j]+ui*n[j]; t2=sa[j-1]=c & mask; c=(c-t2)/radix; j++;
|
|
|
+ c+=sa[j]+ui*n[j]; t2=sa[j-1]=c & mask; c=(c-t2)/radix; j++;
|
|
|
+ }
|
|
|
+ for (;j<kn;) {
|
|
|
+ c+=sa[j]+ui*n[j]; t2=sa[j-1]=c & mask; c=(c-t2)/radix; j++;
|
|
|
+ }
|
|
|
+ for (;j<ks;) {
|
|
|
+ c+=sa[j]; t2=sa[j-1]=c & mask; c=(c-t2)/radix; j++;
|
|
|
+ }
|
|
|
sa[j-1]=c & mask;
|
|
|
}
|
|
|
|
|
@@ -1541,9 +1554,120 @@
|
|
|
}
|
|
|
|
|
|
|
|
|
- // otr.js stuff
|
|
|
+ // otr.js additions
|
|
|
+
|
|
|
+
|
|
|
+ // computes num / den mod n
|
|
|
+ function divMod(num, den, n) {
|
|
|
+ return multMod(num, inverseMod(den, n), n)
|
|
|
+ }
|
|
|
+
|
|
|
+ // computes one - two mod n
|
|
|
+ function subMod(one, two, n) {
|
|
|
+ one = mod(one, n)
|
|
|
+ two = mod(two, n)
|
|
|
+ if (greater(two, one)) one = add(one, n)
|
|
|
+ return sub(one, two)
|
|
|
+ }
|
|
|
+
|
|
|
+ // computes 2^m as a bigInt
|
|
|
+ function twoToThe(m) {
|
|
|
+ var b = Math.floor(m / bpe) + 2
|
|
|
+ var t = new Array(b)
|
|
|
+ for (var i = 0; i < b; i++) t[i] = 0
|
|
|
+ t[b - 2] = 1 << (m % bpe)
|
|
|
+ return t
|
|
|
+ }
|
|
|
+
|
|
|
+ // cache these results for faster lookup
|
|
|
+ var _num2bin = (function () {
|
|
|
+ var i = 0, _num2bin= {}
|
|
|
+ for (; i < 0x100; ++i) {
|
|
|
+ _num2bin[i] = String.fromCharCode(i) // 0 -> "\00"
|
|
|
+ }
|
|
|
+ return _num2bin
|
|
|
+ }())
|
|
|
+
|
|
|
+ // serialize a bigInt to an ascii string
|
|
|
+ // padded up to pad length
|
|
|
+ function bigInt2bits(bi, pad) {
|
|
|
+ pad || (pad = 0)
|
|
|
+ bi = dup(bi)
|
|
|
+ var ba = ''
|
|
|
+ while (!isZero(bi)) {
|
|
|
+ ba = _num2bin[bi[0] & 0xff] + ba
|
|
|
+ rightShift_(bi, 8)
|
|
|
+ }
|
|
|
+ while (ba.length < pad) {
|
|
|
+ ba = '\x00' + ba
|
|
|
+ }
|
|
|
+ return ba
|
|
|
+ }
|
|
|
+
|
|
|
+ // converts a byte array to a bigInt
|
|
|
+ function ba2bigInt(data) {
|
|
|
+ var mpi = str2bigInt('0', 10, data.length)
|
|
|
+ data.forEach(function (d, i) {
|
|
|
+ if (i) leftShift_(mpi, 8)
|
|
|
+ mpi[0] |= d
|
|
|
+ })
|
|
|
+ return mpi
|
|
|
+ }
|
|
|
+
|
|
|
+ // returns a function that returns an array of n bytes
|
|
|
+ var randomBytes = (function () {
|
|
|
+
|
|
|
+ // in node
|
|
|
+ if ( typeof crypto !== 'undefined' &&
|
|
|
+ typeof crypto.randomBytes === 'function' ) {
|
|
|
+ return function (n) {
|
|
|
+ try {
|
|
|
+ var buf = crypto.randomBytes(n)
|
|
|
+ } catch (e) { throw e }
|
|
|
+ return Array.prototype.slice.call(buf, 0)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // in browser
|
|
|
+ else if ( typeof crypto !== 'undefined' &&
|
|
|
+ typeof crypto.getRandomValues === 'function' ) {
|
|
|
+ return function (n) {
|
|
|
+ var buf = new Uint8Array(n)
|
|
|
+ crypto.getRandomValues(buf)
|
|
|
+ return Array.prototype.slice.call(buf, 0)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // err
|
|
|
+ else {
|
|
|
+ throw new Error('Keys should not be generated without CSPRNG.')
|
|
|
+ }
|
|
|
+
|
|
|
+ }())
|
|
|
+
|
|
|
+ // Salsa 20 in webworker needs a 40 byte seed
|
|
|
+ function getSeed() {
|
|
|
+ return randomBytes(40)
|
|
|
+ }
|
|
|
+
|
|
|
+ // returns a single random byte
|
|
|
+ function randomByte() {
|
|
|
+ return randomBytes(1)[0]
|
|
|
+ }
|
|
|
+
|
|
|
+ // returns a k-bit random integer
|
|
|
+ function randomBitInt(k) {
|
|
|
+ if (k > 31) throw new Error("Too many bits.")
|
|
|
+ var i = 0, r = 0
|
|
|
+ var b = Math.floor(k / 8)
|
|
|
+ var mask = (1 << (k % 8)) - 1
|
|
|
+ if (mask) r = randomByte() & mask
|
|
|
+ for (; i < b; i++)
|
|
|
+ r = (256 * r) + randomByte()
|
|
|
+ return r
|
|
|
+ }
|
|
|
|
|
|
- var BigInt = {
|
|
|
+ return {
|
|
|
str2bigInt : str2bigInt
|
|
|
, bigInt2str : bigInt2str
|
|
|
, int2bigInt : int2bigInt
|
|
@@ -1556,130 +1680,26 @@
|
|
|
, equalsInt : equalsInt
|
|
|
, sub : sub
|
|
|
, mod : mod
|
|
|
- , mod_ : mod_
|
|
|
, modInt : modInt
|
|
|
, mult : mult
|
|
|
, divInt_ : divInt_
|
|
|
, rightShift_ : rightShift_
|
|
|
- , leftShift_ : leftShift_
|
|
|
, dup : dup
|
|
|
, greater : greater
|
|
|
, add : add
|
|
|
- , addInt : addInt
|
|
|
- , addInt_ : addInt_
|
|
|
, isZero : isZero
|
|
|
, bitSize : bitSize
|
|
|
- , randTruePrime : randTruePrime
|
|
|
, millerRabin : millerRabin
|
|
|
, divide_ : divide_
|
|
|
, trim : trim
|
|
|
- , expand : expand
|
|
|
- , bpe : bpe
|
|
|
, primes : primes
|
|
|
, findPrimes : findPrimes
|
|
|
, getSeed : getSeed
|
|
|
+ , divMod : divMod
|
|
|
+ , subMod : subMod
|
|
|
+ , twoToThe : twoToThe
|
|
|
+ , bigInt2bits : bigInt2bits
|
|
|
+ , ba2bigInt : ba2bigInt
|
|
|
}
|
|
|
|
|
|
- // from http://davidbau.com/encode/seedrandom.js
|
|
|
-
|
|
|
- var randomBitInt
|
|
|
-
|
|
|
- function seedRand(buf) {
|
|
|
-
|
|
|
- var state = new Salsa20([
|
|
|
- buf[ 0], buf[ 1], buf[ 2], buf[ 3], buf[ 4], buf[ 5], buf[ 6], buf[ 7],
|
|
|
- buf[ 8], buf[ 9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],
|
|
|
- buf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23],
|
|
|
- buf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31]
|
|
|
- ],[
|
|
|
- buf[32], buf[33], buf[34], buf[35], buf[36], buf[37], buf[38], buf[39]
|
|
|
- ])
|
|
|
-
|
|
|
- var width = 256
|
|
|
- , chunks = 6
|
|
|
- , significance = Math.pow(2, 52)
|
|
|
- , overflow = significance * 2
|
|
|
-
|
|
|
- function numerator() {
|
|
|
- var bytes = state.getBytes(chunks)
|
|
|
- var i = 0, r = 0
|
|
|
- for (; i < chunks; i++) {
|
|
|
- r = r * width + bytes[i]
|
|
|
- }
|
|
|
- return r
|
|
|
- }
|
|
|
-
|
|
|
- function randomByte() {
|
|
|
- return state.getBytes(1)[0]
|
|
|
- }
|
|
|
-
|
|
|
- randomBitInt = function (k) {
|
|
|
- if (k > 31) throw new Error("Too many bits.")
|
|
|
- var i = 0, r = 0
|
|
|
- var b = Math.floor(k / 8)
|
|
|
- var mask = (1 << (k % 8)) - 1
|
|
|
- if (mask) r = randomByte() & mask
|
|
|
- for (; i < b; i++)
|
|
|
- r = (256 * r) + randomByte()
|
|
|
- return r
|
|
|
- }
|
|
|
-
|
|
|
- // This function returns a random double in [0, 1) that contains
|
|
|
- // randomness in every bit of the mantissa of the IEEE 754 value.
|
|
|
-
|
|
|
- return function () { // Closure to return a random double:
|
|
|
- var n = numerator() // Start with a numerator n < 2 ^ 48
|
|
|
- , d = Math.pow(width, chunks) // and denominator d = 2 ^ 48.
|
|
|
- , x = 0 // and no 'extra last byte'.
|
|
|
- while (n < significance) { // Fill up all significant digits by
|
|
|
- n = (n + x) * width // shifting numerator and
|
|
|
- d *= width // denominator and generating a
|
|
|
- x = randomByte() // new least-significant-byte.
|
|
|
- }
|
|
|
- while (n >= overflow) { // To avoid rounding up, before adding
|
|
|
- n /= 2 // last byte, shift everything
|
|
|
- d /= 2 // right using integer math until
|
|
|
- x >>>= 1 // we have exactly the desired bits.
|
|
|
- }
|
|
|
- return (n + x) / d // Form the number within [0, 1).
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- function getSeed() {
|
|
|
- var buf
|
|
|
- if ( (typeof crypto !== 'undefined') &&
|
|
|
- (typeof crypto.randomBytes === 'function')
|
|
|
- ) {
|
|
|
- try {
|
|
|
- buf = crypto.randomBytes(40)
|
|
|
- } catch (e) { throw e }
|
|
|
- } else if ( (typeof crypto !== 'undefined') &&
|
|
|
- (typeof crypto.getRandomValues === 'function')
|
|
|
- ) {
|
|
|
- buf = new Uint8Array(40)
|
|
|
- crypto.getRandomValues(buf)
|
|
|
- } else {
|
|
|
- throw new Error('Keys should not be generated without CSPRNG.')
|
|
|
- }
|
|
|
- return Array.prototype.slice.call(buf, 0)
|
|
|
- }
|
|
|
-
|
|
|
- ;(function seed() {
|
|
|
- var HAS_CSPRNG = ((typeof crypto !== 'undefined') &&
|
|
|
- ((typeof crypto.randomBytes === 'function') ||
|
|
|
- (typeof crypto.getRandomValues === 'function')
|
|
|
- ));
|
|
|
- if (!HAS_CSPRNG) {
|
|
|
- return;
|
|
|
- }
|
|
|
- Math.random = seedRand(getSeed())
|
|
|
-
|
|
|
- // reseed every 5 mins (not in ww)
|
|
|
- if ( typeof setTimeout === 'function' && typeof document !== 'undefined' )
|
|
|
- setTimeout(seed, 5 * 60 * 1000)
|
|
|
-
|
|
|
- }())
|
|
|
-
|
|
|
- return BigInt
|
|
|
}))
|