Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,80 @@ | |||
/* This Source Code Form is subject to the terms of the Mozilla Public | |||
* License, v. 2.0. If a copy of the MPL was not distributed with this | |||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |||
|
|||
/* | |||
* abstract out RNG depending on client or server. | |||
* | |||
* auto-seeding has to be requested. | |||
* (the seed is automatic, not the decision to auto-seed.) | |||
* | |||
* nextBytes takes a byteArray as input and populates it, | |||
* because that's how the cool kids do it and so we will not bikeshed. | |||
*/ | |||
|
|||
var utils = require("./utils"), | |||
delay = utils.delay, | |||
libs = require("../libs/minimal"), | |||
sjcl = libs.sjcl; | |||
|
|||
// detect if we have native crypto support | |||
var crypto = null; | |||
try { | |||
crypto = require("crypto"); | |||
} catch(e) {} | |||
|
|||
// proper boolean for whether we have native support | |||
var IS_NATIVE = !!crypto; | |||
|
|||
function NativeRNG() { | |||
} | |||
|
|||
NativeRNG.prototype = { | |||
addEntropy: function(seed_in) { | |||
// do nothing, natively we don't care | |||
}, | |||
autoseed: function(cb) { | |||
// yay, don't need to do anything | |||
if (cb) | |||
delay(cb)(); | |||
}, | |||
nextBytes: function(byteArray) { | |||
var randomBytes = crypto.randomBytes(byteArray.length); | |||
for (var i=0; i<byteArray.length; i++) | |||
byteArray[i] = randomBytes[i]; | |||
} | |||
}; | |||
|
|||
function BrowserRNG() { | |||
} | |||
|
|||
BrowserRNG.prototype = { | |||
// WARNING: assumes that there's enough entropy in here to say it's 256 | |||
addEntropy: function(seed_in) { | |||
sjcl.random.addEntropy(seed_in, 256); | |||
}, | |||
autoseed: function(cb) { | |||
// see if we have window.crypto.getRandomValues | |||
if (window.crypto.getRandomValues) { | |||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong. |
|||
// then sjcl already seeded itself | |||
if (cb) | |||
delay(cb)(); | |||
} else { | |||
sjcl.random.addEventListener('seeded', function(blarg) { | |||
// no passing of arguments to the callback | |||
if (cb) | |||
cb(); | |||
}); | |||
|
|||
// tell sjcl to start collecting some randomness | |||
sjcl.random.startCollectors(); | |||
} | |||
}, | |||
nextBytes: function(byteArray) { | |||
var randomBytes = sjcl.random.randomWords(byteArray.length); | |||
for (var i=0; i<byteArray.length; i++) | |||
byteArray[i] = randomBytes[i]; | |||
} | |||
}; | |||
|
|||
exports.RNG = IS_NATIVE ? NativeRNG : BrowserRNG; | |||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong. |
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,59 @@ | |||
#!/usr/bin/env node | |||
/* This Source Code Form is subject to the terms of the Mozilla Public | |||
* License, v. 2.0. If a copy of the MPL was not distributed with this | |||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |||
|
|||
const | |||
vows = require('vows'), | |||
assert = require('assert'), | |||
rng = require('../lib/rng'); | |||
|
|||
var suite = vows.describe('RNG tests'); | |||
|
|||
suite.addBatch({ | |||
"create rng": { | |||
topic: function() { | |||
return new rng.RNG(); | |||
}, | |||
"looks good": function(rng) { | |||
assert.isObject(rng); | |||
assert.isFunction(rng.addEntropy); | |||
assert.isFunction(rng.autoseed); | |||
assert.isFunction(rng.nextBytes); | |||
}, | |||
"and when we seed": { | |||
topic: function(rng) { | |||
rng.addEntropy("foobar"); | |||
return null; | |||
}, | |||
"all is well": function() { | |||
assert.ok(true); | |||
} | |||
}, | |||
"and when we autoseed": { | |||
topic: function(rng) { | |||
rng.autoseed(this.callback); | |||
}, | |||
"eventually returns": function() { | |||
assert.ok(true); | |||
}, | |||
"and when we get random bytes": { | |||
topic: function(rng) { | |||
var bytes = [0,0,0,0,0,0,0,0,0,0]; | |||
rng.nextBytes(bytes); | |||
return bytes; | |||
}, | |||
"contains stuff": function(bytes) { | |||
assert.isArray(bytes); | |||
}, | |||
"and that stuff is random'ish": function(bytes) { | |||
// this test is unlikely to fail unless no randomness is getting out | |||
assert.ok(!(bytes[0] == 0 && bytes[1] == 0 && bytes[2] == 0)); | |||
} | |||
} | |||
}, | |||
} | |||
}); | |||
// run or export the suite. | |||
if (process.argv[1] === __filename) suite.run(); | |||
else suite.export(module); |
2 comments
on commit eee08ac
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, will addEntropy() be called in a production environment? If so how?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, addEntropy() will be called to mix in some server-side entropy to ensure that clients that have too little entropy can be upgraded.
mightn't this throw if window.crypto is undefined? that may be the case on some browsers.