Assume that I've used white noise from the classic "zener breakdown" circuit to produce 512 bits of random data.

If I use these as the key to a Veracrypt volume, is there any benefit to running 200,000 rounds of sha-512 on them, or is one (or even zero) going to be sufficient?

My reasoning is that there is no plain text to be guessed, an attacker is trying to recover 512 random bits. So they might as well try and brute force the output of the sha-512 rounds, because they're just as likely to get that as they are to get the contents of the key file. Hence those rounds don't actually make the encryption any more secure.

  • derivation helps protect against shortcomings in your random source, if there are any. maybe an xray targeted at your zener could bias it to zero 51% of the time, which would be deadly to security if your ent was not whitened.i would add some out of band data the hash input, like a hi-res cpu time, a system-generated random value, etc. That way, you make any reversal MUCH more difficult, even if your device is confiscated, analyzed, and found to be flawed. many many rounds aren't needed, but 1 round helps a lot.
    – dandavis
    Dec 28 '17 at 16:39
  • I was aware of the security risk of unbiased bits, so I used Von Neumann's algorithm to fix that, It's pretty much a necessity since it's difficult to bias the dc level of the noise source so that I get an exact 50/50 distribution of 1's and 0's. If you expand your comment to an answer, in particular the notes that salting with additional random data (e.g. hi res time) helps, and that many rounds aren't needed, but that 1 helps a lot, I'll mark that as the answer.
    – dgnuff
    Dec 28 '17 at 17:00
  • not a cryptographer, but i dabble. sounds like you're on track. i would use ENT ("ent.exe") to verify the output because VN whitening doesn't have (much) state, so it can't correct against patterns. sha2 will protect against patterns; it's a good whitener, and thus worth running. The "salt" can't hurt, and protects against some later analysis. I don't see any benefit to sha iteration since as you say, you don't have a low-ent input like a password you're protecting w/P-time. i'm just a fool, so i won't answer, but your plan looks good to me.
    – dandavis
    Dec 29 '17 at 5:09


You likely won't benefit much, if at all, from key stretching with SHA-512. In fact, you should not be using your own RNG at all, even if it is based on established physical phenomena. Just use urandom. The longer answer below explains how a computer gets randomness, why using your computer's own randomness is more than sufficient.

How much entropy is present?

The answer depends on how much entropy is present in those 512 bits of random data. If there is at least 128 bits of entropy, then SHA-512 would only be necessary for whitening. You absolutely should whiten it, as a reverse-biased zener diode tends not to have uniformly random output. If there is less than 128 bits of entropy and it could be brute forced otherwise, then key stretching may increase the equivalent entropy (i.e. cracking an 80 bit key with sufficient key stretching may be computationally equivalent to brute forcing a 90 bit key, despite still having only 80 bits of entropy), but the absolute shannon entropy would be unchanged. Most likely, you would be doing nothing but wasting cycles.

Is key stretching with SHA-512 worth it?

Imagine your implementation is broken and is not only biased, but partially predictable. For sake of argument, let's say that every 512 bits of data it outputs contains only 64 bits of entropy (i.e. there are only 264 different possible 512 bit outputs), the equivalent of a 9 character alphanumeric passphrase. Imagine also that an attacker can compute 240 (about 1012) candidate 512 bit outputs per second. At this rate, it would take just a few months to search half the keyspace, which is obviously very bad. Now let's say, for simplicity, that the amount of computation required to generate a single candidate output is identical to the amount required to compute a single SHA-512 digest. By putting your output through 200k hash rounds, you have increased the amount of time it takes to check a single candidate from 1000 per nanosecond, to one every 200 nanoseconds. This would result in it taking more than 50,000 years to search half the keyspace!

Sounds like a great reason to use key stretching, right? Probably not. While it does make what would take a few months instead take longer than the entirety of modern civilization, that is only assuming your generator is broken in a very specific way. Chances are, it'll either be producing well more entropy density than necessary, or so little that no amount of key stretching will help. If the key is 15 bits of entropy lower than the previous example, at 49 bits, will 200k rounds of SHA-512 help? Not at all. It would take "only" about 2 years to search half the keyspace. Would it be necessary if the key had 15 more bits of entropy, at 79 bits? Nope, because at that amount, even with no stretching at all, it would still take 10,000 years to search half the keyspace. Now for a 512 bit output, what are the chances that the output will fall squarely within a < 30 bit range where key stretching is not totally useless, and is not excessive? Quite low. It's better to ensure that your output has sufficient entropy to start out with, which brings us to...

The proper way to generate randomness

I will be assuming you are using a Linux or similar system, as it is what I am most familiar with. This argument should also apply to Windows in a slightly modified form.

I would strongly encourage you not to use such a custom source of randomness for your header key, as they are very easy to implement incorrectly, and have many nasty failure modes, despite being based on a solid theory. If you still want to use a homebrew source, you should generate significantly more than 512 bytes of randomness. Creating a megabyte of data and hashing that with SHA-512 should be sufficient, for example. Ideally, you would use the output of a properly-seeded CSPRNG, such as the /dev/urandom interface on Linux and other Unix-like/Unix-derived operating systems.

Rather than creating your homebrew mixing scheme as well, it seems like your goal is simply to be able to utilize the randomness which can be generated by physical phenomena, either because you don't trust your computer's RNG, or you simply wish to augment it. In this case, rather than using the output of the diode directly, you should add it as a randomness source. The Linux randomness driver allows you to mix in arbitrary data with the entropy pool by writing to either of the random character devices. All it takes is writing to the file itself, and that data will be safely mixed in with the pool, which will take care of all the rest (whitening, tracking entropy estimates, sanity checks, backtracing protection, etc). After doing that, you will be able to safely use VeraCrypt normally, as the entropy produced by your reverse-biased zener diode has been used to augment your kernel's internal pool.

Just use urandom.

"But the kernel's RNG isn't 'true' randomness!"

Sure it is! The Linux kernel gathers randomness from a number of unpredictable events. Some of them are deterministic or at least not entirely non-deterministic, such as packet arrival times on the NIC, but others are truly non-deterministic. The best example is the randomness gathered from interrupts. The Linux randomness driver has a function, add_interrupt_randomness(), called every time an interrupt fires, which mixes in the precise time (in jiffies and cycles since boot) as well as other information such as the IRQ number and current register contents with the entropy pool. These interrupts come from a variety of sources, such as hard drive events, but it also comes from keystrokes. This timing is a source of great, and extremely reliable, randomness.

Extracting randomness from timing

A good timing-based RNG has two components: a fast clock and a slow clock. The fast clock ticks at a very high, precise frequency, while the slow clock ticks, of course, more slowly. If the slow clock, at every tick, samples the current tick count of the fast clock, the output, once whitened, is pretty damn random. Very quickly, the clocks get out of sync. Have you ever been at a stop light, watching two regular, in-sync turn signals slowly get out of sync, until each car seems to be blinking in a discordant pattern? This is exactly how your computer gets entropy from keystrokes. The computer is the fast clock, and the keyboard powers the slow clock. While you may feel like you are typing at a fairly constant rate, that is the perception of your own, 200 ms resolution brain. In reality, to a computer, the amount of time between pressing a key and releasing it, or releasing one key and pressing another, is very long and highly variable. Millions of cycles pass in the time it takes your neurons to wake up, charge, and fire off an action potential. And when they do so, non-deterministic phenomena such as brownian motion causes there to be tremendous variability in the latency of each impulse of a neuron, and that variability directly translates into randomness in the computer.

This is absolutely enough for your purposes. Remember, the multi-billion dollar gambling industry relies on this for a huge percentage of its income. If we did not sport terribly variable, stochastic neurons, the one-armed bandit would be a great way to get rich! The reason it's so effective is because its "fast clock" is a series of spinning cylinders rotating a few times a second, and the slow and inaccurate clock is a person trying their damnedest to accurately time their muscles. If a few cycles per second is "fast" enough to extract enough non-deterministic timing behavior from a human to hold up a massive business, why couldn't a fast clock operating at millions or billions of times per second be enough? All this comes down to the final point: implementing your own RNG is unnecessary. It will either be enough, or it will be broken. The mere act of typing is sufficient to generate just as much entropy, and is far less likely to be broken. If you still want to use your reverse-biased zener diode for fun, go for it! But use it with your system's RNG, not instead of it!

  • As it happens, I'm on Windows, but it has a CryptApi() that provides the equivalent of /dev/urandom. That said, I actually do understand the "fast clock" / "slow clock" principle. So even though I will now use it to feed CryptApi rather than using it directly, the exact M.O. of the hardware rng is to use a slow delay loop that samples the white noise input once every 10 ms to get a bit sequences, and then as mentioned above, apply Von Neumann's algorithm to whiten it. In this context, I'm using eh white noise as the fast clock, and the 10 ms tick as the slow clock.
    – dgnuff
    Dec 30 '17 at 18:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.