2010/12/21 Otto Moerbeek <[email protected]> > > So, there is a lot of effort in get_random_bytes() to get "real random" data > > for the buffer and then the value of nanotime() is prepended to the buffer? > > That does not look right. Please consider: this buffer will be used as key > > for rc4_keysetup() and thus it should contain unrelated and unpredictable > > data. > > I don't know the answer to this question, but my guess is that the > buffer is filled by nanotime() to cover the case that > get_random_bytes() does not have enough entropy available, so at least > some non-constant data is used.
get_random_bytes() calls extract_entropy() which is a a loop around nbytes, thus get_random_bytes() will most certainly deliver enough entropy. So, why do we need a nanotime value in front of the buffer? I'm just thinking about those weaknesses of RC4 if the initial key is not good/strong enough? http://www.rsa.com/rsalabs/node.asp?id=2009 But then, this is "just" the initialization of the PRNG and not the encryption itself, so maybe it has no meaning at all. > > HOWEVER, right after the call of rc4_crypt(), we call rc4_keysetup() with > > the same 'arc4random_state'. This makes the call to rc4_crypt() useless, as > > the data structure will be overwritten again with the init data of the RC4 > > function. > > rc4_crypt() changes both the state and the contents of buf, since buf is > used both as source and destination. That buf is used by rc4_keysetup() > to create a new state. So indeed the state is overwritten, but the > contents of buf produced by rc4_crypt() is used to do that. So both > calls serve their purpose. yes, you are right! I did not see the changes to buf in rc4_crypt(). Sorry for that! But still, why is it done this way? I compared the implementation of arc4_stir with the one in libc (src/lib/libc/crypt/arc4random.c). The implementations are somehow different. The in libc the rc4 state is only initialized once at the first call of arc4_stir() and then there are consecutive calls to arc4_addrandom() which is the equivalent of rc4_crypt(). So, there is a difference in the implementation. May this is just due to different authors. First question: Which one is the 'correct' implementation, as proposed in Applied Cryptography (hint in libc -> arc4random.c)? Second question: Does it matter if the implementation is different than the one in Applied Cryptography? A last thing: From: src/lib/libc/crypt/arc4random.c arc4_stir(void) { <snip> /* * Discard early keystream, as per recommendations in: * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps */ for (i = 0; i < 256; i++) (void)arc4_getbyte(); arc4_count = 1600000; } The first 256 Bytes will be skipped due to the mentioned paper. Similar code exists in rnd.c. /* * Throw away the first N words of output, as suggested in the * paper "Weaknesses in the Key Scheduling Algorithm of RC4" * by Fluher, Mantin, and Shamir. (N = 256 in our case.) */ rc4_skip(&arc4random_state, 256 * 4); mtx_leave(&rndlock); However here, 1024 bytes (256 * 4) will be skipped. Maybe that's just a misinterpretation of what a "word" is (byte or integer). Maybe I'm paranoid and see problems where there are none. But then, this is part of the crypto code and there should be no open questions about the implementation details. Regards Kurt Knochner http://knochner.com/
