whyzdev / ppp-pam

Automatically exported from code.google.com/p/ppp-pam
BSD 3-Clause "New" or "Revised" License
0 stars 0 forks source link

UUID doesn't seem to be a Perfect source of randomness #26

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Test program generating random 256 bit keys like pppauth does without/with
use of sha256:
#include <stdio.h>
#include <uuid/uuid.h>

int main(int argc, char **argv)
{
    uuid_t uuid;
    int i;
    unsigned char entropy[32];
    for (;;) {
        uuid_generate_time(uuid);
        for (i=0; i<16; i++) {
            entropy[i] = uuid[i];
        }

        uuid_generate_random(uuid);
        for (i=0; i<16; i++) {
            entropy[i+16] = uuid[i];
        }

        // without sha256 for now

        if (fwrite(entropy, sizeof(entropy), 1, stdout) != 1)
            return 1;
    }

    return 0;
}

Randomity test:
% ./uuid_test | rngtest -c 5000
rngtest 2
Copyright (c) 2004 by Henrique de Moraes Holschuh
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

rngtest: starting FIPS tests...
rngtest: bits received from input: 100000032
rngtest: FIPS 140-2 successes: 0
rngtest: FIPS 140-2 failures: 5000
rngtest: FIPS 140-2(2001-10-10) Monobit: 4962
rngtest: FIPS 140-2(2001-10-10) Poker: 5000
rngtest: FIPS 140-2(2001-10-10) Runs: 4997
rngtest: FIPS 140-2(2001-10-10) Long run: 0
rngtest: FIPS 140-2(2001-10-10) Continuous run: 0
rngtest: input channel speed: (min=4.318; avg=26.187; max=19073.486)Mibits/s
rngtest: FIPS tests speed: (min=122.266; avg=194.849; max=202.909)Mibits/s
rngtest: Program run time: 4143023 microseconds

That's lots of failures! Compare to:
% cat /dev/urandom| rngtest -c 5000

rngtest: bits received from input: 100000032
rngtest: FIPS 140-2 successes: 4992
rngtest: FIPS 140-2 failures: 8
rngtest: input channel speed: (min=1.042; avg=97.223; max=19073.486)Mibits/s
rngtest: FIPS tests speed: (min=50.863; avg=148.624; max=160.281)Mibits/s
rngtest: Program run time: 1649105 microseconds

Of course calculating sha256 from this data makes it a lot better (30
failures/5000 successes instead of 100%), but worries me nevertheless, as 
calculating sha256 from a variable, which is incremented by one in each
pass also gets this rate but is not random at all.

Using openssl like this:

int main(int argc, char **argv)
{
        uuid_t uuid;
        int i;
        unsigned char entropy[32];
        for (;;) {
                if (RAND_bytes(entropy, 32) == 0)
                        return 1;

                if (fwrite(entropy, sizeof(entropy), 1, stdout) != 1)
                        return 1;
        }

        return 0;
}

Will result in more tests passed:
rngtest: starting FIPS tests...
rngtest: bits received from input: 100000032
rngtest: FIPS 140-2 successes: 4994
rngtest: FIPS 140-2 failures: 6
rngtest: input channel speed: (min=2.951; avg=566.423; max=19073.486)Mibits/s
rngtest: FIPS tests speed: (min=45.305; avg=137.873; max=160.281)Mibits/s
rngtest: Program run time: 868945 microseconds

While most secure would be to read /dev/random I guess. Previous methods 
worked nearly instantly, while this approach for -c 5000 would take ages. 
I left it with -c 50... and after 8 minutes it generated only one block
(20000 bits) which were a... SUCCESS! Duh. But 258 bits can be generated
pretty fast especially if one moves the mouse/types on keyboard.

I don't want to pull openssl as dependency, I'll try with some combined
approach.

Original issue reported on code.google.com by TomaszFo...@gmail.com on 11 Nov 2009 at 6:10