If you are needing to generate cryptographically secure random numbers, you should almost always use the operating system's CSPRNG; that is, /dev/urandom
, CryptGenRandom
, getrandom
, getentropy
, or the like. This will be secure, well-seeded, well-tested, and generally foolproof.
In the unlikely event that you actually need a different CSPRNG, then the PRNG entropy should either be drawn from the system CSPRNG or another CSPRNG that is seeded from the system one. For example, in the event you really need to generate random numbers very quickly and the OS generator is not fast enough, you could use a per-thread CSPRNG seeded from the OS generator.
We assume that an attacker knows how your code is designed and structured, so if you seed a CSPRNG with easily guessable values like the PID, time, or user ID, then it's likely that an attacker will be able to guess future output based on seeing a small amount of output.
If you don't need cryptographic security, you can draw the seed from any source you like, but the OS CSPRNG is not a bad choice if you don't care very much but just want a good seed. For non-cryptographic purposes, I like ChaCha8 (which is a cryptographic algorithm, but with 8 rounds is insufficiently conservative) as my PRNG because it is generally faster than most alternatives, has good statistical properties, and can easily be seeded with any 32- or 64-bit value by just repeating that value as the key. In such a case, as long as the seed is unlikely to repeat, it will probably produce good output.