There are many ways to combine random number generators:
XOR the outputs. Very simple and fast. If they are independent and at least one is strong, the output is strong as well. However, if those assumptions are not true, this can be very broken.
Hash the outputs. With a strong hash you combine the entropy of both. Good if the RNGs have some entropy, but their output is not uniform. Can be significantly slower, if your RNGs are fast.
Seed one using the other. Mostly used for seeding a CSPRNG with a true RNG. If the former is weak or the latter doesn't have enough entropy, the whole is weak as well.
Entropy pool, with multiple inputs combined into a large state, which is iterated to produce the next state and hashed to produce output. Can include pseudo-random inputs, but a normal PRNG is not a good input.
In practice, if you have a CSPRNG, seeding with a random number (3.) is the only one you should be concerned with. If you have poor, non-cryptographic PRNGs, no games you play with the outputs will get you anything better than (or usually even as good as) simply moving to a CSPRNG.
An entropy pool is usually already available in the OS (/dev/urandom
or CryptGenRandom
), so there are few situations where you should go there yourself. Number 2. is often used in TRNGs for whitening, but that too is not something you should usually need to be doing in software. Maybe, if paranoid about the design, you could be seeding two completely different CSPRNGs with true entropy, then XORing the outputs, but then you are trusting on them to really be independent.