Skip to content

Instantly share code, notes, and snippets.

@sarciszewski
Last active March 15, 2019 13:03
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save sarciszewski/88a7ed143204d17c3e42 to your computer and use it in GitHub Desktop.
Save sarciszewski/88a7ed143204d17c3e42 to your computer and use it in GitHub Desktop.
Javascript CSPRNG for Integers
/**
* License: WTFPL, CC0, ZAP (Zero For 0wned Anti-copyright Pledge), etc
*/
function secure_rand(min, max) {
var i = rval = bits = bytes = 0;
var range = max - min;
if (range < 1) {
return min;
}
if (window.crypto && window.crypto.getRandomValues) {
// Calculate Math.ceil(Math.log(range, 2)) using binary operators
var tmp = range;
/**
* mask is a binary string of 1s that we can & (binary AND) with our random
* value to reduce the number of lookups
*/
var mask = 1;
while (tmp > 0) {
if (bits % 8 === 0) {
bytes++;
}
bits++;
mask = mask << 1 | 1; // 0x00001111 -> 0x00011111
tmp = tmp >>> 1; // 0x01000000 -> 0x00100000
}
var values = new Uint8Array(bytes);
do {
window.crypto.getRandomValues(values);
// Turn the random bytes into an integer
rval = 0;
for (i = 0; i < bytes; i++) {
rval |= (values[i] << (8 * i));
}
// Apply the mask
rval &= mask;
// We discard random values outside of the range and try again
// rather than reducing by a modulo to avoid introducing bias
// to our random numbers.
} while (rval > range);
// We should return a value in the interval [min, max]
return (rval + min);
} else {
// CSPRNG not available, fail closed
throw Error('placeholder; this should be customized with accordance to whatever practices are best for Node.js')
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment