SecureRandom in JavaScript?
There is no such helper function in JS. You can generates a fairly random hash using:
function hex(n){
n = n || 16;
var result = '';
while (n--){
result += Math.floor(Math.random()*16).toString(16).toUpperCase();
}
return result;
}
You can modify it to form a guid:
function generateGuid(){
var result = '', n=0;
while (n<32){
result += (~[8,12,16,20].indexOf(n++) ? '-': '') +
Math.floor(Math.random()*16).toString(16).toUpperCase();
}
return result;
}
I was led to this question as a top search engine result using the following keywords:
- securerandom range js
- securerandom js
As such, I thought it would be good to update this post with a working answer available today (2019):
The snippet below employs Crypto.getRandomValues()
for sourcing random values said to be,
... cryptographically strong ... using a pseudo-random number generator seeded with a value with enough entropy ... suitable for cryptographic usages.
Thus, we have:
var N = 32;
var rng = window.crypto || window.msCrypto;
var rawBytes = Array
.from(rng.getRandomValues(new Uint8Array(N)))
.map(c => String.fromCharCode(c))
.join([]);
Source: JavaScript-based Password Generator
Now, below is a fun little hex-encoder I cooked up as a one-liner using some Array
functions for looping:
function hexEncode(s) {
return s.split('').map(c => (c < String.fromCharCode(16) ? '0' : '') + c.charCodeAt(0).toString(16)).join([]);
}
Finally, if you want to combine the two above for generating random hashes, you can just swap out and adapt the .map()
function accordingly and package it up like so:
function secureRandomHash(N) {
N = N || 32; // Coalesce if size parameter N is left undefined
// TODO: Consider refactoring with lazy-loaded function
// to set preferred RNG provider, else throw an error here
// to generate noise that no secure RNG is available for
// this application.
var rng = window.crypto || window.msCrypto;
return Array
.from(rng.getRandomValues(new Uint8Array(N)))
.map(c => (c < 16 ? '0' : '') + c.toString(16)).join([]);
}
Happy coding!
Edit: Turns out I ended up needing this in my own project which also implements the suggested TODO in the previous example (lazy-loading) so here we go:
Math.secureRandom = function() {
var rng = window.crypto || window.msCrypto;
if (rng === undefined)
throw 'No suitable RNG found';
// Lazy-load this if- branch
Math.secureRandom = function() {
// More secure implementation of Math.random (https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues#Examples)
return rng.getRandomValues(new Uint32Array(1))[0] / 4294967296;
};
return Math.secureRandom();
}
Or if you're feeling really adventurous...
// Auto-upgrade Math.random with a more secure implementation only if crypto is available
(function() {
var rng = window.crypto || window.msCrypto;
if (rng === undefined)
return;
// Source: https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues#Examples
Math.random = function() {
return rng.getRandomValues(new Uint32Array(1))[0] / 4294967296;
};
})();
console.log(Math.random());
Whether extending Math
or overwriting Math.random()
for a drop-in replacement is appropriate for your application or target audience is left purely as an academic exercise to the implementor. Be sure to check with your architect first! License MIT here of course :)