diff --git a/jsbn/rng.js b/jsbn/rng.js index 03afc3a..2169874 100644 --- a/jsbn/rng.js +++ b/jsbn/rng.js @@ -1,58 +1,49 @@ // Random number generator - requires a PRNG backend, e.g. prng4.js - -// For best results, put code like -// -// in your main HTML document. - var rng_state; var rng_pool; var rng_pptr; -// Mix in a 32-bit integer into the pool -function rng_seed_int(x) { - rng_pool[rng_pptr++] ^= x & 255; - rng_pool[rng_pptr++] ^= (x >> 8) & 255; - rng_pool[rng_pptr++] ^= (x >> 16) & 255; - rng_pool[rng_pptr++] ^= (x >> 24) & 255; - if(rng_pptr >= rng_psize) rng_pptr -= rng_psize; -} - -// Mix in the current time (w/milliseconds) into the pool -function rng_seed_time() { - rng_seed_int(new Date().getTime()); -} - // Initialize the pool with junk if needed. if(rng_pool == null) { rng_pool = new Array(); rng_pptr = 0; var t; - if(navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) { - // Extract entropy (256 bits) from NS4 RNG if available - var z = window.crypto.random(32); - for(t = 0; t < z.length; ++t) - rng_pool[rng_pptr++] = z.charCodeAt(t) & 255; - } - while(rng_pptr < rng_psize) { // extract some randomness from Math.random() - t = Math.floor(65536 * Math.random()); - rng_pool[rng_pptr++] = t >>> 8; - rng_pool[rng_pptr++] = t & 255; - } - rng_pptr = 0; - rng_seed_time(); - //rng_seed_int(window.screenX); - //rng_seed_int(window.screenY); + if(window.crypto && window.crypto.getRandomValues) { + // Extract entropy (2048 bits) from RNG if available + var z = new Uint32Array(256); + window.crypto.getRandomValues(z); + for (t = 0; t < z.length; ++t) + rng_pool[rng_pptr++] = z[t] & 255; + } + + // Use mouse events for entropy, if we do not have enough entropy by the time + // we need it, entropy will be generated by Math.random. + var onMouseMoveListener = function(ev) { + this.count = this.count || 0; + if (this.count >= 256 || rng_pptr >= rng_psize) { + window.removeEventListener("mousemove", onMouseMoveListener); + return; + } + this.count += 1; + var mouseCoordinates = ev.x + ev.y; + rng_pool[rng_pptr++] = mouseCoordinates & 255; + }; + + window.addEventListener("mousemove", onMouseMoveListener); } function rng_get_byte() { if(rng_state == null) { - rng_seed_time(); rng_state = prng_newstate(); + // At this point, we may not have collected enough entropy. If not, fall back to Math.random + while (rng_pptr < rng_psize) { + var random = Math.floor(65536 * Math.random()); + rng_pool[rng_pptr++] = random & 255; + } rng_state.init(rng_pool); for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr) rng_pool[rng_pptr] = 0; rng_pptr = 0; - //rng_pool = null; } // TODO: allow reseeding after first request return rng_state.next();