10
$\begingroup$

I need to generate a CA (4096-bit RSA) and server keys for openvpn and I want them to be "top quality". Here is my plan:

  • gather entropy from multiple sources (saving individual files): FreeBSD Yarrow, Linux (with haveged daemon while entropy_avail is 4096), ANU QRNG, something else (e.g. wifi capture file encrypted with a random password, other suggestions)
  • mix all random files into a single one
  • use the result to seed openssl -rand [myrndfile] when generating the keys

If my plan sounds ok:

  • what size should the random files be?
  • what would be the best method to mix the files into a single one?
$\endgroup$
1
  • 1
    $\begingroup$ It would be very interesting if one answer to this question here would also enlighten where the random bytes are used in the RSA key creation process? $\endgroup$ Mar 16, 2014 at 16:27

2 Answers 2

8
$\begingroup$

First off, using '-rand' is only seeding the OpenSSL RNG. It can be 1 byte or 1 TB. It's only used as a seed to get things started internally. Then, OpenSSL will use the systems entropy to actually generate the primes needed by RSA.

Further, entropy is just a measure of unpredictability in a sequence, not an actual pool of stored bits. The larger the estimation on entropy, the more likely certain things will have unpredictable behaviors, such as a sequence of random numbers.

Again though, the Linux kernel file /proc/sys/kernel/random/entropy_avail is just an estimation. When you have an entropy pool of "4096 bits", this just means that the random numbers being generated have the highest quality of unpredictability you can produce. As the entropy pool estimation drops, the confidence in the sequence of random numbers also drops. When the entropy pool is 0, the kernel will block at generating random data until the pool can be filled again. As you generate random data, it reduces the estimation on entropy. This is the behavior of /dev/random.

In other words, think of the entropy pool as a "crypto thermometer". When the meter is at "full up", the generated numbers will be very difficult, if not near impossible to reproduce, and highly unpredictable. When the meter is completely empty, generating random bits could be reproduced by a 3rd party with little knowledge of the system accurately.

So, getting to your OpenSSL key question. OpenSSL will want the kernel to keep entropy as full as possible. However, OpenSSL will seed from /dev/urandom by default. This device will still exhaust entropy, but rather than block when there is no entropy estimate, it will use a PRNG to generate the rest of the data. Keep the entropy pool filled, and the PRNG will never been utilized.

The /dev/random device on FreeBSD is a strict PRNG, and not a TRNG. As you mentioned, it uses the Yarow algorithm to generate random numbers. However, after generating 2^256 numbers, the cycle repeats, generating the exact same numbers in the exact same order as before, as is the case with all PRNGs. By comparison, /dev/urandom in the Linux kernel uses SHA1, which will generate a total of 2^160 numbers before recycling when the entropy pool is exhausted.

Now, to address your question. You mentioned that you are using haveged(8) with Linux to keep the entropy reserve full. On most systems, haveged(8) is generating about 1 MBps of true random data to the kernel, and using the ioctl() system call to increase the entropy counter. As such, generating your 4096-bit RSA OpenSSL key will have the highest quality of cryptographic strength you could ask for, and adding additional random data from other systems won't increase its strength.

The whole point of the certificate generation is to create random numbers from either your file, or from a random number generator, as noise input into an algorithm to generate very large primes. The trick is getting to those prime numbers. With an entropy pool of 4096 bits, at full up, all the time, as haveged(8) will be providing, the ability of someone to regenerate the same primes, even if they have full knowledge of your system, is highly improbable.

So, in my opinion, run haveged(8) keeping the kernel topped at 4096-bits of entropy, and just generate your certificate there using "-rand /dev/random", rather than generating a file from every system.

$\endgroup$
6
  • $\begingroup$ Thank you very much for your insightful reply. Maybe I am paranoid, but I don't want to fully trust haveged as single entropy source. I don't have a links collections now, but I'm sure I stumbled across some articles (including here on stackexchange) which were not too positive on haveged. Therefore, I'd prefer to use haveged with other sources - just in case haveged turns out to be flawed someday. OpenSSL can use multiple entropy files with the -rand ( -rand file1:file2:file3 etc) parameter, so it would be easier this way to provide it some good/tested (rngtest, ent) sources to seed its RNG. $\endgroup$
    – Vincent
    Dec 24, 2013 at 21:11
  • $\begingroup$ I reached the characters limit on my previous reply. Thoughts on the method, please? $\endgroup$
    – Vincent
    Dec 24, 2013 at 21:13
  • $\begingroup$ As you mentioned, use '-rand file1 -rand file2 ...' etc with all your files, 4K each. Otherwise, haveged(8) doesn't work well in virtualization environments, where the daemon is running in a VM. It's also difficult to get a lot of random data off embedded devices. On bare hardware though, it works really well, and passes all the statistical analysis tests, such as rng-tools(1) and the Dieharder tests. Unless you have an untrustworthy TRNG chip, it's pretty difficult to get more random data than data that passes all the quality assurance tests for randomness. $\endgroup$ Dec 25, 2013 at 14:19
  • 1
    $\begingroup$ Above answers suggest that data is read from /dev/urandom which exhausts and then uses a PNRG to continue. In (this eustion](unix.stackexchange.com/q/119967/24394) I generated 2048 RSA using openssl and it only ever reads 32bytes. 32bytes do not drain urandom. 32bytes seesm too little. $\endgroup$ Mar 16, 2014 at 16:22
  • $\begingroup$ When the meter is completely empty, generating random bits could be reproduced by a 3rd party with little knowledge of the system accurately. This is incorrect. The only reason it blocks is because it is no longer information theoretic secure, and a powerful preimage attack against SHA-1 could allow predicting future output. It is not true that the randomness quality would be reduced when the entropy estimate goes down to zero. $\endgroup$
    – forest
    Dec 15, 2017 at 5:04
1
$\begingroup$

The OpenSSL Wiki and source code both point to the random seed function only using the first 32 bytes (256 bits) supplied to seed the cryptographically strong PRNG. Any additional bytes get discarded. That being said, good practice would be to seed with with the full 32 bytes and make them as "random" as possible. Additionally, the the function should be force re-seeded or called again fresh with a new seed for each new key or random number being generated to guarantee that the same stream from the CS-PRNG isn't being used for more than one key. If you have a lot of data you believe is random and really feel you must incorporate all of it, then use a hash function to generate the 32 byte seed (however, then you place trust in the hash function not to have weaknesses (but this is probably one of the lesser worries). Summary: Generate the best 32 byte seeds you can and reseed often.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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