2010/12/21 Otto Moerbeek <o...@drijf.net>

> > 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/

Reply via email to