Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Secure random numbers in javascript?

How do I generate cryptographically secure random numbers in javascript?

like image 520
Kyle Avatar asked Nov 03 '10 00:11

Kyle


People also ask

Is JavaScript math random secure?

Note: Math. random() does not provide cryptographically secure random numbers. Do not use them for anything related to security. Use the Web Crypto API instead, and more precisely the window.

Is SecureRandom () method available in JavaScript?

@some Yes, you're totally right.

Is random choice () cryptographically secure?

Random numbers and data generated by the random class are not cryptographically protected. An output of all random module functions is not cryptographically secure, whether it is used to create a random number or pick random elements from a sequence.

Is SecureRandom truly random?

The basic and important difference between both is SecureRandom generate more non predictable random numbers as it implements Cryptographically Secure Pseudo-Random Number Generator (CSPRNG) as compare to Random class which uses Linear Congruential Generator (LCG).


2 Answers

There's been discussion at WHATWG on adding this to the window.crypto object. You can read the discussion and check out the proposed API and webkit bug (22049).

Just tested the following code in Chrome to get a random byte:

(function(){    var buf = new Uint8Array(1);    window.crypto.getRandomValues(buf);    alert(buf[0]);  })();
like image 124
Paul V Avatar answered Oct 01 '22 18:10

Paul V


In order, I think your best bets are:

  1. window.crypto.getRandomValues or window.msCrypto.getRandomValues
  2. The sjcl library's randomWords function (http://crypto.stanford.edu/sjcl/)
  3. The isaac library's random number generator (which is seeded by Math.random, so not really cryptographically secure) (https://github.com/rubycon/isaac.js)

window.crypto.getRandomValues has been implemented in Chrome for a while now, and relatively recently in Firefox as well. Unfortunately, Internet Explorer 10 and before do not implement the function. IE 11 has window.msCrypto, which accomplishes the same thing. sjcl has a great random number generator seeded from mouse movements, but there's always a chance that either the mouse won't have moved sufficiently to seed the generator, or that the user is on a mobile device where there is no mouse movement whatsoever. Thus, I recommend having a fallback case where you can still get a non-secure random number if there is no choice. Here's how I've handled this:

function GetRandomWords (wordCount) {     var randomWords;      // First we're going to try to use a built-in CSPRNG     if (window.crypto && window.crypto.getRandomValues) {         randomWords = new Int32Array(wordCount);         window.crypto.getRandomValues(randomWords);     }     // Because of course IE calls it msCrypto instead of being standard     else if (window.msCrypto && window.msCrypto.getRandomValues) {         randomWords = new Int32Array(wordCount);         window.msCrypto.getRandomValues(randomWords);     }     // So, no built-in functionality - bummer. If the user has wiggled the mouse enough,     // sjcl might help us out here     else if (sjcl.random.isReady()) {         randomWords = sjcl.random.randomWords(wordCount);     }     // Last resort - we'll use isaac.js to get a random number. It's seeded from Math.random(),     // so this isn't ideal, but it'll still greatly increase the space of guesses a hacker would     // have to make to crack the password.     else {         randomWords = [];         for (var i = 0; i < wordCount; i++) {             randomWords.push(isaac.rand());         }     }      return randomWords; }; 

You'll need to include sjcl.js and isaac.js for that implementation, and be sure to start the sjcl entropy collector as soon as your page is loaded:

sjcl.random.startCollectors(); 

sjcl is dual-licensed BSD and GPL, while isaac.js is MIT, so it's perfectly safe to use either of those in any project. As mentioned in another answer, clipperz is another option, however for whatever bizarre reason, it is licensed under the AGPL. I have yet to see anyone who seems to understand what implications that has for a JavaScript library, but I'd universally avoid it.

One way to improve the code I've posted might be to store the state of the isaac random number generator in localStorage, so it isn't reseeded every time the page is loaded. Isaac will generate a random sequence, but for cryptography purposes, the seed is all-important. Seeding with Math.random is bad, but at least a little less bad if it isn't necessarily on every page load.

like image 28
ZeroG Avatar answered Oct 01 '22 18:10

ZeroG