134 lines
4.4 KiB
JavaScript
134 lines
4.4 KiB
JavaScript
/* basic entropy accumulator */
|
|
var accum = (function() {
|
|
|
|
var pool, // randomness pool
|
|
time, // start timestamp
|
|
last; // last step timestamp
|
|
|
|
/* initialize with default pool */
|
|
function init() {
|
|
pool = [];
|
|
time = new Date().getTime();
|
|
last = time;
|
|
// use Math.random
|
|
pool.push((Math.random() * 0xffffffff)|0);
|
|
// use current time
|
|
pool.push(time|0);
|
|
}
|
|
|
|
/* perform one step */
|
|
function step() {
|
|
if (!to)
|
|
return;
|
|
if (pool.length >= 255) { // stop at 255 values (1 more is added on fetch)
|
|
stop();
|
|
return;
|
|
}
|
|
var now = new Date().getTime();
|
|
// use actual time difference
|
|
pool.push(now-last);
|
|
// always compute, occasionally use Math.random
|
|
var rnd = (Math.random() * 0xffffffff)|0;
|
|
if (now % 2)
|
|
pool[pool.length-1] += rnd;
|
|
last = now;
|
|
to = setTimeout(step, 100+Math.random()*512); // use hypothetical time difference
|
|
}
|
|
|
|
var to = null;
|
|
|
|
/* starts accumulating */
|
|
function start() {
|
|
if (to) return;
|
|
to = setTimeout(step, 100+Math.random()*512);
|
|
if (console.log)
|
|
console.log("bcrypt-isaac: collecting entropy...");
|
|
// install collectors
|
|
if (typeof window !== 'undefined' && window && window.addEventListener)
|
|
window.addEventListener("load", loadCollector, false),
|
|
window.addEventListener("mousemove", mouseCollector, false),
|
|
window.addEventListener("touchmove", touchCollector, false);
|
|
else if (typeof document !== 'undefined' && document && document.attachEvent)
|
|
document.attachEvent("onload", loadCollector),
|
|
document.attachEvent("onmousemove", mouseCollector);
|
|
}
|
|
|
|
/* stops accumulating */
|
|
function stop() {
|
|
if (!to) return;
|
|
clearTimeout(to); to = null;
|
|
// uninstall collectors
|
|
if (typeof window !== 'undefined' && window && window.removeEventListener)
|
|
window.removeEventListener("load", loadCollector, false),
|
|
window.removeEventListener("mousemove", mouseCollector, false),
|
|
window.removeEventListener("touchmove", touchCollector, false);
|
|
else if (typeof document !== 'undefined' && document && document.detachEvent)
|
|
document.detachEvent("onload", loadCollector),
|
|
document.detachEvent("onmousemove", mouseCollector);
|
|
}
|
|
|
|
/* fetches the randomness pool */
|
|
function fetch() {
|
|
// add overall time difference
|
|
pool.push((new Date().getTime()-time)|0);
|
|
var res = pool;
|
|
init();
|
|
if (console.log)
|
|
console.log("bcrypt-isaac: using "+res.length+"/256 samples of entropy");
|
|
// console.log(res);
|
|
return res;
|
|
}
|
|
|
|
/* adds the current time to the top of the pool */
|
|
function addTime() {
|
|
pool[pool.length-1] += new Date().getTime() - time;
|
|
}
|
|
|
|
/* page load collector */
|
|
function loadCollector() {
|
|
if (!to || pool.length >= 255)
|
|
return;
|
|
pool.push(0);
|
|
addTime();
|
|
}
|
|
|
|
/* mouse events collector */
|
|
function mouseCollector(ev) {
|
|
if (!to || pool.length >= 255)
|
|
return;
|
|
try {
|
|
var x = ev.x || ev.clientX || ev.offsetX || 0,
|
|
y = ev.y || ev.clientY || ev.offsetY || 0;
|
|
if (x != 0 || y != 0)
|
|
pool[pool.length-1] += ((x-mouseCollector.last[0]) ^ (y-mouseCollector.last[1])),
|
|
addTime(),
|
|
mouseCollector.last = [x,y];
|
|
} catch (e) {}
|
|
}
|
|
mouseCollector.last = [0,0];
|
|
|
|
/* touch events collector */
|
|
function touchCollector(ev) {
|
|
if (!to || pool.length >= 255)
|
|
return;
|
|
try {
|
|
var touch = ev.touches[0] || ev.changedTouches[0];
|
|
var x = touch.pageX || touch.clientX || 0,
|
|
y = touch.pageY || touch.clientY || 0;
|
|
if (x != 0 || y != 0)
|
|
pool[pool.length-1] += (x-touchCollector.last[0]) ^ (y-touchCollector.last[1]),
|
|
addTime(),
|
|
touchCollector.last = [x,y];
|
|
} catch (e) {}
|
|
}
|
|
touchCollector.last = [0,0];
|
|
|
|
init();
|
|
return {
|
|
"start": start,
|
|
"stop": stop,
|
|
"fetch": fetch
|
|
}
|
|
|
|
})();
|