Should we really rely on "Cryptographically Secure Pseudo-Random Number Generators" (CSPRNG) alone to guarantee secure random output?
No, we should not rely on CSPRNGs alone for secure random output. For this task, a CSPRNGs requires a truly (not pseudo) random input (the seed). Lacking that, different instances of the same CSPRNG that reuse the same seed will generate the same output when reset (e.g. the program is run again, the device is reset). Using CSPRNGs seeded with no or insufficient randomness is a most classical source of security compromise; see e.g. Mining Your Ps and Qs: Detection of Widespread Weak Keys in Network Devices.
Would it be over-engineering to, for example, hash the random numbers a random amount of times too, for instance when using the CSPRNG in client-side JavaScript?
Yes, what's proposed is poorly-thought over-engineering.
"Pseudo" (the P in CSPRNG and PRNG) means providing repeatable results from run to run, absent variable input. If we use a (CS)PRNG to decide how many times itself is run, it remains a (CS)PRNG. The problem discussed above is not solved, or even meaningfully mitigated. We get a false impression of extra security.
What works to a better degree is mixing several sources of randomness at the input of a CSPRNG, and using that CSPRNG. In client-side JavaScript, the sources could be a system-supplied hopefully-true RNG (possibly Math.random()
if nothing better is known to be available), cursor location and system time sampled at various instants determined by network or user-interface events (keypresses), a server-supplied nonce, and as a last resort keyboard input. The CSPRNG could be built from a hash function.
Whether that's over-engineering or not depends on security goal, threat model, and runtime environment. The later is often not known when writing the code. Many browsers at some point in their history had insecure Math.random()
and supplied no secure alternative, making IMHO such precaution sound.
Update following comment
using a hash ( CSPRNG output, available client data, available server data ) would provide more security than just using the CSPRNG?
Yes, if these three conditions hold:
- The hash is secure for modern definition of that (assimilable to a PRF).
- And the apparent entropy in "CSPRNG output" (for one not knowing it's secret seed) is at least the width of the hash; e.g. if this output is $n$ decimal digit, $n\log_2(10)$ bits.
- And at least about 1 bit worth of the extra data inputs is unpredictable to the adversary. Without that condition, the entropy in the output can be reduced by 0.83 bit (see this), which may be a (usually very minor) issue.
This is valid for hash too narrow for collision-resistance or preimage-resistance (e.g. SHA-256 truncated to 80 bit), and remains valid if we replace "CSPRNG" with whatever available RNG. There are slightly better ways to combine extra entropy, but that one is already a worthwhile improvement.