| 1 | /* basic entropy accumulator */
|
|---|
| 2 | var accum = (function() {
|
|---|
| 3 |
|
|---|
| 4 | var pool, // randomness pool
|
|---|
| 5 | time, // start timestamp
|
|---|
| 6 | last; // last step timestamp
|
|---|
| 7 |
|
|---|
| 8 | /* initialize with default pool */
|
|---|
| 9 | function init() {
|
|---|
| 10 | pool = [];
|
|---|
| 11 | time = new Date().getTime();
|
|---|
| 12 | last = time;
|
|---|
| 13 | // use Math.random
|
|---|
| 14 | pool.push((Math.random() * 0xffffffff)|0);
|
|---|
| 15 | // use current time
|
|---|
| 16 | pool.push(time|0);
|
|---|
| 17 | }
|
|---|
| 18 |
|
|---|
| 19 | /* perform one step */
|
|---|
| 20 | function step() {
|
|---|
| 21 | if (!to)
|
|---|
| 22 | return;
|
|---|
| 23 | if (pool.length >= 255) { // stop at 255 values (1 more is added on fetch)
|
|---|
| 24 | stop();
|
|---|
| 25 | return;
|
|---|
| 26 | }
|
|---|
| 27 | var now = new Date().getTime();
|
|---|
| 28 | // use actual time difference
|
|---|
| 29 | pool.push(now-last);
|
|---|
| 30 | // always compute, occasionally use Math.random
|
|---|
| 31 | var rnd = (Math.random() * 0xffffffff)|0;
|
|---|
| 32 | if (now % 2)
|
|---|
| 33 | pool[pool.length-1] += rnd;
|
|---|
| 34 | last = now;
|
|---|
| 35 | to = setTimeout(step, 100+Math.random()*512); // use hypothetical time difference
|
|---|
| 36 | }
|
|---|
| 37 |
|
|---|
| 38 | var to = null;
|
|---|
| 39 |
|
|---|
| 40 | /* starts accumulating */
|
|---|
| 41 | function start() {
|
|---|
| 42 | if (to) return;
|
|---|
| 43 | to = setTimeout(step, 100+Math.random()*512);
|
|---|
| 44 | if (console.log)
|
|---|
| 45 | console.log("bcrypt-isaac: collecting entropy...");
|
|---|
| 46 | // install collectors
|
|---|
| 47 | if (typeof window !== 'undefined' && window && window.addEventListener)
|
|---|
| 48 | window.addEventListener("load", loadCollector, false),
|
|---|
| 49 | window.addEventListener("mousemove", mouseCollector, false),
|
|---|
| 50 | window.addEventListener("touchmove", touchCollector, false);
|
|---|
| 51 | else if (typeof document !== 'undefined' && document && document.attachEvent)
|
|---|
| 52 | document.attachEvent("onload", loadCollector),
|
|---|
| 53 | document.attachEvent("onmousemove", mouseCollector);
|
|---|
| 54 | }
|
|---|
| 55 |
|
|---|
| 56 | /* stops accumulating */
|
|---|
| 57 | function stop() {
|
|---|
| 58 | if (!to) return;
|
|---|
| 59 | clearTimeout(to); to = null;
|
|---|
| 60 | // uninstall collectors
|
|---|
| 61 | if (typeof window !== 'undefined' && window && window.removeEventListener)
|
|---|
| 62 | window.removeEventListener("load", loadCollector, false),
|
|---|
| 63 | window.removeEventListener("mousemove", mouseCollector, false),
|
|---|
| 64 | window.removeEventListener("touchmove", touchCollector, false);
|
|---|
| 65 | else if (typeof document !== 'undefined' && document && document.detachEvent)
|
|---|
| 66 | document.detachEvent("onload", loadCollector),
|
|---|
| 67 | document.detachEvent("onmousemove", mouseCollector);
|
|---|
| 68 | }
|
|---|
| 69 |
|
|---|
| 70 | /* fetches the randomness pool */
|
|---|
| 71 | function fetch() {
|
|---|
| 72 | // add overall time difference
|
|---|
| 73 | pool.push((new Date().getTime()-time)|0);
|
|---|
| 74 | var res = pool;
|
|---|
| 75 | init();
|
|---|
| 76 | if (console.log)
|
|---|
| 77 | console.log("bcrypt-isaac: using "+res.length+"/256 samples of entropy");
|
|---|
| 78 | // console.log(res);
|
|---|
| 79 | return res;
|
|---|
| 80 | }
|
|---|
| 81 |
|
|---|
| 82 | /* adds the current time to the top of the pool */
|
|---|
| 83 | function addTime() {
|
|---|
| 84 | pool[pool.length-1] += new Date().getTime() - time;
|
|---|
| 85 | }
|
|---|
| 86 |
|
|---|
| 87 | /* page load collector */
|
|---|
| 88 | function loadCollector() {
|
|---|
| 89 | if (!to || pool.length >= 255)
|
|---|
| 90 | return;
|
|---|
| 91 | pool.push(0);
|
|---|
| 92 | addTime();
|
|---|
| 93 | }
|
|---|
| 94 |
|
|---|
| 95 | /* mouse events collector */
|
|---|
| 96 | function mouseCollector(ev) {
|
|---|
| 97 | if (!to || pool.length >= 255)
|
|---|
| 98 | return;
|
|---|
| 99 | try {
|
|---|
| 100 | var x = ev.x || ev.clientX || ev.offsetX || 0,
|
|---|
| 101 | y = ev.y || ev.clientY || ev.offsetY || 0;
|
|---|
| 102 | if (x != 0 || y != 0)
|
|---|
| 103 | pool[pool.length-1] += ((x-mouseCollector.last[0]) ^ (y-mouseCollector.last[1])),
|
|---|
| 104 | addTime(),
|
|---|
| 105 | mouseCollector.last = [x,y];
|
|---|
| 106 | } catch (e) {}
|
|---|
| 107 | }
|
|---|
| 108 | mouseCollector.last = [0,0];
|
|---|
| 109 |
|
|---|
| 110 | /* touch events collector */
|
|---|
| 111 | function touchCollector(ev) {
|
|---|
| 112 | if (!to || pool.length >= 255)
|
|---|
| 113 | return;
|
|---|
| 114 | try {
|
|---|
| 115 | var touch = ev.touches[0] || ev.changedTouches[0];
|
|---|
| 116 | var x = touch.pageX || touch.clientX || 0,
|
|---|
| 117 | y = touch.pageY || touch.clientY || 0;
|
|---|
| 118 | if (x != 0 || y != 0)
|
|---|
| 119 | pool[pool.length-1] += (x-touchCollector.last[0]) ^ (y-touchCollector.last[1]),
|
|---|
| 120 | addTime(),
|
|---|
| 121 | touchCollector.last = [x,y];
|
|---|
| 122 | } catch (e) {}
|
|---|
| 123 | }
|
|---|
| 124 | touchCollector.last = [0,0];
|
|---|
| 125 |
|
|---|
| 126 | init();
|
|---|
| 127 | return {
|
|---|
| 128 | "start": start,
|
|---|
| 129 | "stop": stop,
|
|---|
| 130 | "fetch": fetch
|
|---|
| 131 | }
|
|---|
| 132 |
|
|---|
| 133 | })();
|
|---|