How trustworthy is javascript's random impleme

2019-01-14 15:56发布

问题:

I would like to do some experimenting with javascript and encryption and I got curious as to how unpredictable the implementation of the random function is. Has anyone done any hard tests?

Clearly browsers have the ability to generate strong randomness (for ssl). The questions is do they give javascript access to the same strength.

回答1:

Generally, the random function is not cryptographically strong, for that you need to make sure you are using a cryptographic pseudo-random-number generator.

Generic random functions generally don't use cryptographically strong generation methods because they take longer than simple ones, (eg. Yarrow is more complicated than Mersenne Twister) and require careful management of the entropy pool, which is not a guarantee that Mozilla, cstdlib, etc. want to make to you.

If you need access to cryptographically strong random number generators, I'd look into getting access to the underlying SSL implementation (which a given browser may or may not allow access to).



回答2:

Recent browsers expose window.crypto.getRandomValues() which is cryptographically strong.

There are also JS libraries that implement strong RNGs but without getRandomValues() it's very hard part to collect entropy. It can be done from mouse & keyboard though it may take a long time.

Math.random() was weak in most browsers in 2008 - Amit Klein's paper goes into excellent detail - and sadly is almost as weak today.

UPDATE: It seems practically all browsers switched in 2015–2016 to XorShift128+ — a fast variant on LFSR tuned to good statistical properties but also very weak cryptographically: https://lwn.net/Articles/666407/, https://security.stackexchange.com/questions/84906/predicting-math-random-numbers. Details below are out of date.

  • Firefox used a very weak "our own homebrew LFSR" algorithm; they've been discussing switching to a stronger algoritm and entropy source since 2006 (bug 322529). UPDATE: in 2015 they switched to XorShift128+.

    In May 2013 they at least switched the seed from current time to good entropy sources (bug 868860), also removing(?) cross-tab leakage.

  • Webkit uses a weak fast algorithm (GameRand) since 2009 but seeds since 2010 (in each context) from a strong RNG initialized from strong OS sources.
    (I presume this is what Safari uses but I may be confused about the various WebKit ports...)

  • Chrome doesn't use WebKit's random, does its own in V8, a weak linear thing.
    There is no agreement whether Math.random() should be strong (bug 246054).

    Not sure how it's seeded. V8 has SetEntropySource() hook, but apparently it was only introduced for unit testing, not called by Chrome. If not called, random() is used for seeding.

    State became per-context in 2011 but that's not very useful with weak seeding.

  • Opera declared it fixed in Jan 2009 and say here that their Math.random() is cryptographically strong.

  • Didn't find documentation on what IE does nowdays. They had a weak linear PRNG in 2008 (see paper). They did tell Amit they'll fix it in a service pack, so there might be an advisory somewhere...



回答3:

Each of the JavaScript engines I'm familiar with do not use cryptographically-strong RNGs.

If you need a good source of entropy in a browser (and preferably don't need it very often), I would recommend capturing mouse movement data and running it through a cryptographically-strong hashing algorithm. Existing programs such as the Entropy Gathering Daemon (used with gpg) can be used as a reference for how to implement such a system.



回答4:

One interesting data point I found is mozilla has a javascript crypto object that isn't fully implemented yet.



回答5:

Generally you can't rely on pseudo random number generation in javascript to be even remotely cryptographically secure. You might consider implementing your own PNRG using an entropy gathering system, or perhaps using an external source of random numbers such as hotbits.