Entropy of system data - use all and hash, or trim least significant bits? I'm working on a background entropy collector for key generation that monitors hardware and produces an entropy pool.

Here's my list of sources:


Mouse position
Keyboard timings (i.e. time between keystrokes)
Network


Bytes sent
Bytes received
Datagrams sent
Datagrams received

Processor (per CPU)


Interrupts/sec
Queued DPCs/sec
C3 Transitions/sec

Memory


Page Faults/sec
Transition Faults/sec

Disk


Write bytes/sec
Read bytes/sec

Process (total)


IO Read Bytes/sec
IO Write Bytes/sec
IO Other Bytes/sec
Page Faults/sec

USB


Interrupt Bytes/sec
Controller PCI Interrupts/sec

Time taken to fetch all of the above data (measured using QueryPerformanceCounter)


These stats are collected once every 330ms. At the moment, I'm just globbing all the data into an array of around 100 bytes. I then hash the array using SHA512, to add a total of 64 bytes to the entropy pool, giving me roughly 200 bytes per second.

The pool is initially populated by the hash of a single timestamp value indicating the system boot time. When the pool reaches 64KB, I xor with the oldest 64-byte block. This is somewhat warned against in another question, but I don't foresee a problem because the pool is very large and the reasoning for removing old data is size. Keys are generated by computing a cryptographic hash of the entire entropy pool.

This seems reasonable, but I wonder whether SHA512 is overkill. Would I be better off extracting the least significant bits of each statistic into a bitstream? If so, how many? Are there any other issues with my approach?
What you are doing sounds a lot like what the /dev/random and /dev/urandom or the PRNGD on many systems already do:
those systems take an arbitrary large sequence of numbers (from a true hardware random number generator if available, or else from environmental noise such as keystroke timing)
and feed it into a CSPRNG.
The CSPRNG internally maintains an &quot;entropy pool&quot;,
and thoroughly &quot;mixes&quot; the pool whenever it produces a new output value.
The output is made available via /dev/random and /dev/urandom .

Have you considered possibly using the /dev/random or PRNGD already running and available on your system?
Have you considered possibly downloading the source code to some CSPRNG that has already been written, tested, debugged, and checked for security flaws, rather than writing your own from scratch?


At the moment, I'm just globbing all the data into an array of around 100 bytes. I then hash the array using SHA512, to add a total of 64 bytes to the entropy pool
Would I be better off extracting the least significant bits of each statistic into a bitstream?

Rather than collecting a batch of data, hashing it, and then feeding that into the CSPRNG,
it's better to simply feed the batch of data directly onto the CSPRNG.
(The CSPRNG already handles the &quot;hashing&quot; stuff internally).
At best, your hash operation preserves whatever entropy exists in the source data;
at worst, it is unnecessarily throwing away some of that entropy.
SHA512 is an excellent hash function, so hashing the incoming data with SHA512 is OK but unnecessary.
(The idea of &quot;XOR all the collected bits&quot; seems to throw away too much entropy).
The high-order bits of most of those statistics have very little usable entropy -- however, assuming the CSPRNG is properly written, that doesn't hurt anything.
A properly written CSPRNG is just as secure even when one of the inputs doesn't have any entropy -- such as an input that is always &quot;000000000000000...&quot;.
If, hypothetically, you are forced to cut back on the number of inputs to your CSPRNG in order for some reason,
you would want to preserve as much entropy as possibly by cutting out such zero-entropy (all-zeroes) and low-entropy (high-order bits of these other stats) before cutting out higher-entropy sources.

When the pool reaches 64KB...

Wow. That many bits in the entropy pool is overkill in our universe.

Keys are generated by computing a cryptographic hash of the entire entropy pool.

Yes, that's how most CSPRNG produce their output values.

FreeBSD and AIX implement /dev/random using the Yarrow algorithm
OpenBSD implements /dev/random using an algorithm based on RC4 (is this the same as ISAAC ?)
Fortuna
My understanding is that many other CSPRNG implementations have a way to feed in more bits of entropy.

(I'm re-using a lightly edited of a previous answer I wrote,
PRNG taking advantage of very large seed
)