| /** | 
|  * An API for getting cryptographically-secure random bytes. The bytes are | 
|  * generated using the Fortuna algorithm devised by Bruce Schneier and | 
|  * Niels Ferguson. | 
|  * | 
|  * Getting strong random bytes is not yet easy to do in javascript. The only | 
|  * truish random entropy that can be collected is from the mouse, keyboard, or | 
|  * from timing with respect to page loads, etc. This generator makes a poor | 
|  * attempt at providing random bytes when those sources haven't yet provided | 
|  * enough entropy to initially seed or to reseed the PRNG. | 
|  * | 
|  * @author Dave Longley | 
|  * | 
|  * Copyright (c) 2009-2014 Digital Bazaar, Inc. | 
|  */ | 
| var forge = require('./forge'); | 
| require('./aes'); | 
| require('./sha256'); | 
| require('./prng'); | 
| require('./util'); | 
|   | 
| (function() { | 
|   | 
| // forge.random already defined | 
| if(forge.random && forge.random.getBytes) { | 
|   module.exports = forge.random; | 
|   return; | 
| } | 
|   | 
| (function(jQuery) { | 
|   | 
| // the default prng plugin, uses AES-128 | 
| var prng_aes = {}; | 
| var _prng_aes_output = new Array(4); | 
| var _prng_aes_buffer = forge.util.createBuffer(); | 
| prng_aes.formatKey = function(key) { | 
|   // convert the key into 32-bit integers | 
|   var tmp = forge.util.createBuffer(key); | 
|   key = new Array(4); | 
|   key[0] = tmp.getInt32(); | 
|   key[1] = tmp.getInt32(); | 
|   key[2] = tmp.getInt32(); | 
|   key[3] = tmp.getInt32(); | 
|   | 
|   // return the expanded key | 
|   return forge.aes._expandKey(key, false); | 
| }; | 
| prng_aes.formatSeed = function(seed) { | 
|   // convert seed into 32-bit integers | 
|   var tmp = forge.util.createBuffer(seed); | 
|   seed = new Array(4); | 
|   seed[0] = tmp.getInt32(); | 
|   seed[1] = tmp.getInt32(); | 
|   seed[2] = tmp.getInt32(); | 
|   seed[3] = tmp.getInt32(); | 
|   return seed; | 
| }; | 
| prng_aes.cipher = function(key, seed) { | 
|   forge.aes._updateBlock(key, seed, _prng_aes_output, false); | 
|   _prng_aes_buffer.putInt32(_prng_aes_output[0]); | 
|   _prng_aes_buffer.putInt32(_prng_aes_output[1]); | 
|   _prng_aes_buffer.putInt32(_prng_aes_output[2]); | 
|   _prng_aes_buffer.putInt32(_prng_aes_output[3]); | 
|   return _prng_aes_buffer.getBytes(); | 
| }; | 
| prng_aes.increment = function(seed) { | 
|   // FIXME: do we care about carry or signed issues? | 
|   ++seed[3]; | 
|   return seed; | 
| }; | 
| prng_aes.md = forge.md.sha256; | 
|   | 
| /** | 
|  * Creates a new PRNG. | 
|  */ | 
| function spawnPrng() { | 
|   var ctx = forge.prng.create(prng_aes); | 
|   | 
|   /** | 
|    * Gets random bytes. If a native secure crypto API is unavailable, this | 
|    * method tries to make the bytes more unpredictable by drawing from data that | 
|    * can be collected from the user of the browser, eg: mouse movement. | 
|    * | 
|    * If a callback is given, this method will be called asynchronously. | 
|    * | 
|    * @param count the number of random bytes to get. | 
|    * @param [callback(err, bytes)] called once the operation completes. | 
|    * | 
|    * @return the random bytes in a string. | 
|    */ | 
|   ctx.getBytes = function(count, callback) { | 
|     return ctx.generate(count, callback); | 
|   }; | 
|   | 
|   /** | 
|    * Gets random bytes asynchronously. If a native secure crypto API is | 
|    * unavailable, this method tries to make the bytes more unpredictable by | 
|    * drawing from data that can be collected from the user of the browser, | 
|    * eg: mouse movement. | 
|    * | 
|    * @param count the number of random bytes to get. | 
|    * | 
|    * @return the random bytes in a string. | 
|    */ | 
|   ctx.getBytesSync = function(count) { | 
|     return ctx.generate(count); | 
|   }; | 
|   | 
|   return ctx; | 
| } | 
|   | 
| // create default prng context | 
| var _ctx = spawnPrng(); | 
|   | 
| // add other sources of entropy only if window.crypto.getRandomValues is not | 
| // available -- otherwise this source will be automatically used by the prng | 
| var getRandomValues = null; | 
| var globalScope = forge.util.globalScope; | 
| var _crypto = globalScope.crypto || globalScope.msCrypto; | 
| if(_crypto && _crypto.getRandomValues) { | 
|   getRandomValues = function(arr) { | 
|     return _crypto.getRandomValues(arr); | 
|   }; | 
| } | 
|   | 
| if(forge.options.usePureJavaScript || | 
|   (!forge.util.isNodejs && !getRandomValues)) { | 
|   // if this is a web worker, do not use weak entropy, instead register to | 
|   // receive strong entropy asynchronously from the main thread | 
|   if(typeof window === 'undefined' || window.document === undefined) { | 
|     // FIXME: | 
|   } | 
|   | 
|   // get load time entropy | 
|   _ctx.collectInt(+new Date(), 32); | 
|   | 
|   // add some entropy from navigator object | 
|   if(typeof(navigator) !== 'undefined') { | 
|     var _navBytes = ''; | 
|     for(var key in navigator) { | 
|       try { | 
|         if(typeof(navigator[key]) == 'string') { | 
|           _navBytes += navigator[key]; | 
|         } | 
|       } catch(e) { | 
|         /* Some navigator keys might not be accessible, e.g. the geolocation | 
|           attribute throws an exception if touched in Mozilla chrome:// | 
|           context. | 
|   | 
|           Silently ignore this and just don't use this as a source of | 
|           entropy. */ | 
|       } | 
|     } | 
|     _ctx.collect(_navBytes); | 
|     _navBytes = null; | 
|   } | 
|   | 
|   // add mouse and keyboard collectors if jquery is available | 
|   if(jQuery) { | 
|     // set up mouse entropy capture | 
|     jQuery().mousemove(function(e) { | 
|       // add mouse coords | 
|       _ctx.collectInt(e.clientX, 16); | 
|       _ctx.collectInt(e.clientY, 16); | 
|     }); | 
|   | 
|     // set up keyboard entropy capture | 
|     jQuery().keypress(function(e) { | 
|       _ctx.collectInt(e.charCode, 8); | 
|     }); | 
|   } | 
| } | 
|   | 
| /* Random API */ | 
| if(!forge.random) { | 
|   forge.random = _ctx; | 
| } else { | 
|   // extend forge.random with _ctx | 
|   for(var key in _ctx) { | 
|     forge.random[key] = _ctx[key]; | 
|   } | 
| } | 
|   | 
| // expose spawn PRNG | 
| forge.random.createInstance = spawnPrng; | 
|   | 
| module.exports = forge.random; | 
|   | 
| })(typeof(jQuery) !== 'undefined' ? jQuery : null); | 
|   | 
| })(); |