What I am trying to do is generate a large (4096bit) random number in JavaScript that is cryptographically safe to use.

My approach is the following:

  1. I am creating a Uint8Array with the desired length.
  2. I am using Math.random() to prefill it.
  3. I am showing a a 256x256pixel box, and show a message asking for moving the mouse around in it. For every onmousemove event, I am selecting a random byte in the array (using Math.random again), and doing a bitwise XOR with the relative X position of the mouse cursor, and doing the same to another random byte, with the Y position.
  4. I keep processing onmousemove events until N events have been processed. (N >= a lot)

So what I have in the end is an array that was prefilled by an insecure random number generator, but whose output was mixed around with a lot of user-generated entropy.

My question is: Would the resulting number be safe to use? Or am I missing some glaring insecurity in this approach?

  • $\begingroup$ Over-engineered. Collect all mouse samples over some time $t$ (massively overestimate the time needed - better too much than not enough) instructing the user to furiously move the mouse around (do not record samples which occur more than twice in a row, it means he isn't moving his mouse), and feed it all into a hash function to distill 256 or 512 bits of entropy. Stretch as needed. That said you might look into existing frameworks to generate cryptographic numbers in Javascript - some already exist, and creating your own algorithm is generally not the answer. $\endgroup$ – Thomas Jul 16 '13 at 14:15
  • $\begingroup$ I know there are existing frameworks. This is more of an exercise for myself. Trying to get into cryptographic thinking :) $\endgroup$ – user7676 Jul 16 '13 at 14:19
  • $\begingroup$ See Generate cryptographically strong pseudorandom numbers in Javascript? on security.SE $\endgroup$ – CodesInChaos Jul 16 '13 at 14:34
  • $\begingroup$ Your approach is certainly much worse than hashing all the raw entropy with SHA-2 and then expanding it to the desired size. $\endgroup$ – CodesInChaos Jul 16 '13 at 14:39
  • $\begingroup$ Right. So hashing is the answer, then. Thanks, guys! $\endgroup$ – user7676 Jul 16 '13 at 15:01

I would take a look at https://github.com/mdp/gibberish-aes/ From that you can see well implemented ECMAscript, (javascript) and AES can be used to generate random numbers. It might be slightly over-kill for your needs, but should not let you down in the medium-term.

| improve this answer | |
  • $\begingroup$ Using strong crypto in the RNG is the easy part. The real problem is entropy gathering. Which sources to use, and how to estimate the entropy. One really common issue is allowing consumers to read from the PRNG before enough initial entropy has been gathered. $\endgroup$ – CodesInChaos Jul 19 '13 at 8:12
  • $\begingroup$ @CodesInChaos What is "enough" entropy? $\endgroup$ – user7676 Jul 25 '13 at 0:23
  • $\begingroup$ @user7676 Depends on the target security level, but somewhere between 100 and 200 bits. $\endgroup$ – CodesInChaos Jul 25 '13 at 0:43
  • $\begingroup$ tools.ietf.org/html/rfc6485 (2012) demands 2048 bits for asymmetrical which is roughly comparable to 128 bit symmetrical. I really like the idea of an algorithm that calculates required entropy based on the year: keylength.com/en/1 $\endgroup$ – Alexx Roche Jul 26 '13 at 10:19
  • $\begingroup$ CodesInChaos, what is the default entropy pool for js? Is it browser based? $\endgroup$ – Charles Hoskinson Nov 2 '13 at 1:35

Not the answer you're looking for? Browse other questions tagged or ask your own question.