Here is arc4random.c from the LibreSSL pseudorandom generator as used in OpenBSD.

It works as follows:

  1. Take 40 "truly random" bytes from OS (PRG seed);
  2. Use the seed as key and IV to generate 1024 bytes of ChaCha keystream;
  3. Use the last 984 bytes of the keystream as a PRG output, and the first 40 bytes as the key and IV to generate the next 1024 of ChaCha keystream;
  4. Repeat until the total number of keystream bytes exceed the limit; after that reseed (go to the step 1).

I don't quite understand the purpose of the step 3 (see the lines 135-138 of the linked code):

/* immediately reinit for backtracking resistance */
_rs_init(rsx->rs_buf, KEYSZ + IVSZ);
memset(rsx->rs_buf, 0, KEYSZ + IVSZ);
rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ;

Why isn’t the whole keystream as a PRG output used? Why does the "rekeying" step make the PRG more secure?


This is to prevent two different types of attacks.

  1. Bias attacks. It may in the future be that ChaCha20 is broken like RC4 is and that you can recover the secret key (or something equivalent) only given enough parts of the keystream. By re-keying often enough you can limit the length of the keystream for each given key, rendering those attacks impossible.
  2. State recovery attacks. Assume an attacker learns the state of the PRNG at some point in time. Now while he can still predict future bits, he won't be able to predict past bits beyond the last re-key, because the key needed to do this is gone and you can't recover it from the current key (if you could you could passively recover the key from a short fragment of the keystream).
| improve this answer | |

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.