# Does AES encrypting /dev/zero and feeding output to AES again increase entropy of the ciphertext?

I just thought about what would change if would pipe the output of

openssl enc -aes-256-ctr -pass pass:"$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64)" -nosalt < /dev/zero | pv -pterb > file  to AES again. What this does is take a passphrase out of urandom and encrypt the output of /dev/zero - so taking 1 passphrase and an endless number of zeros, which outputs random numbers. this way AES is used as a random number generator. This line can be used to fill up a file on a disk with random numbers. It's way faster than dd'ing /dev/urandom to a file. One can also substitute "file" with /dev/null, just to see how fast the system is encrypting and writing to null. So I wonder what happens if I would feed the output of that line to AES again. **Would the output change in a way? As I think it should not change anything — the randomness of the output should be exactly the same, shouldn't it? Is there a practical way to measure the entropy of the output?** I think no, as it should be good enough to not have any statistical anomalies, so there's no way of measuring an increased/decreased entropy - or am I missing/confusing something? • Wow, that's a lot of pipey redirects. It might help to explain what it all does. That way non unix people can more easily contribute... – Paul Uszak Nov 29 '18 at 21:56 • ok, i found it on the net. – Peter Fleix Nov 29 '18 at 21:58 • If you found the solution please explain it here so someone else who has the same question can see the answer. – Filip Franik Nov 29 '18 at 22:16 • no i mean i found the line on the net as an alternative to write output of dev/urandom to a file. – Peter Fleix Nov 29 '18 at 22:18 ## 2 Answers Wow, that's 7 times faster than /dev/urandom. Counter intuitively though, and in the general case, simply pulling a stream from /dev/urandom would have a greater entropy than your OpenSSL line. You don't need to re-encrypt with another AES. The randomness of your scheme depends on the 128 bits of entropy marshalled by the dd command for use as a key. So no matter how long file is, it will only ever be one of $$2^{128}$$ possible sequences. It will always have 128 bits of unknown entropy. You don't have to measure it. To paint/post a picture, the current Linux random number generator looks like:- with /dev/urandom sitting there in the top right. (/dev/urandom is the output of the ChaCha20 cipher which is analogous to the AES bit in your scheme.) However, the ChaCha20 cipher is often reseeded from entropy pools (in the centre and right). (Un)fortunately, you've picked what is probably the most complex random number generator in the world to ask your question about. It's a little difficult to determine the exact reseed rate, but the existence of a reseed function means that any long sequence will have triggered reseed events. That's partly why it's so much slower, but also due to a non optimised ChaCha implementation. Thus such a sequence will have $$n \times 256$$ bits of unknown entropy, where $$n$$ is the number of reseed events. So I suppose you could loosely say that /dev/urandom is more random than your OpenSSL scheme. Unless you have a nuclear arsenal in your shed, I don't think that it makes a tangible difference though. Notes: 1. The best work on the Linux generator I've ever seen is here, so you can judge the difficulty of measuring /dev/*random entropy. 2. AES (AES) will have identical byte distributions and so not introduce any statistical anomalies. • Why would it be counter intuitive that drawing from a random number generator includes more entropy? For the notes: (1) it's using the bytes as input for the OpenSSL PBKDF (not a good idea) (3) 256 bit would be required to defeat quantum computers - I wonder if you should use that term at all as it it seems to defeat your argument rather than help it (4) what do you mean with "AES (AES)"? Please clarify in the (upvoted) answer. – Maarten Bodewes Nov 30 '18 at 1:34 • I can indeed guess what happened. But I also see that even if I give a concrete counterexample (quantum computing) that you seem to ignore it. And yes, although I don't think going over 128 bit gives much of an advantage. But AES-256 does not cost that much either and has more rounds. It would not be that hard to upgrade the security of the current scheme to 256 bits (currently it certainly does not provide it for multiple reasons). Anyway: removed is removed, and I cannot upvote more :) – Maarten Bodewes Nov 30 '18 at 4:34 • How is the Linux kernel RNG complicated? And it is easily known how often it reseeds: once every 300 seconds (5 minutes) if there is sufficient entropy in the input pool. And the reseed is not why it is slower, so I'm not sure where you got that incorrect bit of information. In fact the reseed is nothing more than writing 256 bits of data to an array. This unoptimized horror is why it's so slow. – forest Nov 30 '18 at 7:47 • @MaartenBodewes There is another reason to go with 256-bit ciphers, and that is multitarget attacks. – forest Nov 30 '18 at 7:55 • @PaulUszak ChaCha20 is not a block cipher. – forest Dec 1 '18 at 2:24 First lets quickly analyze your commands: 1. $(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64) : take a block of 128 pseudo-random bytes and put it into a single line encoded as base 64, throwing away anything printed to standard error
2. openssl enc -aes-256-ctr -pass pass:(1) -nosalt < /dev/zero :
1. perform OpenSSL key derivation on the base 64 string from step (1) without a salt: basically two subsequent runs of HMAC-MD5 to create 256 bits of output;
2. use the resulting key to perform AES-256 CTR encryption on an endless stream of zeros to get to the counter mode key stream;
3. pv -pterb > file : perform some metrics before dumping the key stream to file.

Now your question is if you would replace the /dev/null with the input file, using a new block of 128 bytes taken from /dev/urandom as password. Well, the good news is that it will add another amount of randomness to the original stream. How much entropy that entails depends on the internal characteristics of the used /dev/urandom implementation. Of course, if you would use the original password then you would cancel out the operation and produce a file with all zeros.

Using CTR to create a fast PRNG is a good idea that is used quite a lot. But remember that although it is very fast, it doesn't reseed. Using /dev/urandom is a bad idea if you want to have as much entropy as possible though. For this kind of use /dev/random is a better choice.

Using a bad password generation mechanism such as the default OpenSSL one will however bring back the maximum amount of entropy to 128 bit max due to MD5 being used to derive the key. If you consider that you could have up to 128 bytes of entropy, that's quite a shame. You would be better off using the -K option which allows for hexadecimal encoded keys instead. In that case you retrieve 32 bytes of randomness and use the full 256 bits of that directly for AES-CTR.

So if you want to increase the possible entropy, try and use this:

openssl enc -aes-256-ctr -K "\$(dd if=/dev/random bs=32 count=1 2>/dev/null | od  -v -An -tx1 | tr -d ' \n')" -iv 00000000000000000000000000000000


and use it on any number of zeros. Note that on some systems this may deplete the entropy pool if you perform a lot of these commands.

Here -K is used to replace the password with a 256 bit key, which is supplied in hexadecimals using the dd if=/dev/random bs=32 count=1 2>/dev/null | od -v -An -tx1 | tr -d ' \n') command, where od creates hexadecimals including spaces and newlines, which are removed using the tr command. The IV can be kept to all zero as the key will differ for each command anyway.

Final note: writing random data to an intermediate file is usually not a good idea. You are much better off programming this. In case you require OpenSSL then you could use C or any wrapper library for your choice of language that gives you enough functionality.