rubycon / isaac.js

A JavaScript implementation of the ISAAC PRNG
50 stars 17 forks source link

entropy used for seeding #2

Open timkuijsten opened 10 years ago

timkuijsten commented 10 years ago

Looking quickly at the code seems to implicate that the initial seed is taken from Math.random [1]. As this discussion about Math.random in different browsers points out [2] this is not a strong source and having started the discussion at https://github.com/dcodeIO/bcrypt.js/issues/16 I was wondering if you as the author of this library might be able to elaborate a bit on the subject?

[1] https://github.com/rubycon/isaac.js/blob/master/isaac.js#L103 [2] https://stackoverflow.com/questions/578700/how-trustworthy-is-javascripts-random-implementation-in-various-browsers#answer-18507748

rubycon commented 10 years ago

Although most of Math.random() implementations aren't crypto-secure algorithms, the important parts to look up are how these implementations are seeded and if they're independently seeded across windows/tabs. In my opinion the biggest limitation of Math.random() is that it doesn't provide much bits of entropy at each run. But yes, Math.random() was never intented to be crypto-secure in the first place.

When I wrote this bit of code it was unfortunately the only standard entropy source across every JS engine/API. I use it as a default seeding function, if the user doesn't call isaac.seed(). Now things seem to have change with the W3C Web Crypto API, which isn't fully supported yet but one particularly useful function is pretty well supported: crypto.getRandomValues() (or crypto.randomBytes() in Node.js) ...but what if your user has an older browser?

When it comes to fallback there's only two options: a fast/pratical one, "graceful degradation" to a weaker source of entropy (the ubiquitous Math.random() or 4) or slow/more secure one, stop the process until enough entropy is available (by gathering info from keyboard and mouse events[1]). Graceful degradation is a dangerous concept in cryptography but the other option can make your application much less responsive and can you trust your user for generating enough strong entropy? In both case I think you have to warn your user of what's going on (which I haven't done in ISAAC.js...).

And even if seeding is the Achilles' heel of in-browser CSPRNG, you have a bigger problem.

[1] Gathering enough entropy from an user might take some time. Furthermore, today touchscreens provide way less entropy than good ol' mouse movements. O'Reilly's "Secure Programming Cookbook" provides some good recipes for mouse/keyboard entropy gathering. Fortuna is a CSPRNG which have an entropy gathering/estimation mechanism, but not sure of how it has been implemented in JS.

timkuijsten commented 10 years ago

"When it comes to fallback there's only two options: a fast/pratical one, "graceful degradation" to a weaker source of entropy (the ubiquitous Math.random() or 4) or slow/more secure one, stop the process until enough entropy is available (by gathering info from keyboard and mouse events[1])." then "... and can you trust your user for generating enough strong entropy?"

Well there sort of is a third option, fail hard since you can not guarantee the promise of delivering a CSPRNG in such environments.

"In both case I think you have to warn your user of what's going on (which I haven't done in ISAAC.js...)."

I was unable to find any warnings in the code. I see ;-) Well I'm questioning if the current default/codebase is really giving the user a CSPRNG like promised, or that it is an insecure PRNG. I think this should be known to those who use it.

Just fyi, both twin-bcrypt and bcryptjs have updated there code to hard fail by default if neither nodejs crypto nor WebCrypto API are available.

Offirmo commented 1 year ago

Old to the party, but note that ISAAC-32 claims to be cryptographically secure:

Although it is “designed to be cryptographically secure”, no security proof is given, and only statistical tests argue for its security

ref: https://eprint.iacr.org/2006/438.pdf