#if 0
From msuinfo!agate!spool.mu.edu!howland.reston.ans.net!EU.net!ieunet!ieunet!vax1.dcu.ie!75001969 Fri May 20 10:14:04 1994
Path: msuinfo!agate!spool.mu.edu!howland.reston.ans.net!EU.net!ieunet!ieunet!vax1.dcu.ie!75001969
From: 75001969@vax1.dcu.ie
Newsgroups: sci.crypt
Subject: RE: Random Number Analysis Code
Message-ID: <1994May18.122836.1251@vax1.dcu.ie>
Date: 18 May 94 12:28:36 GMT
Lines: 76


By popular demand (well 2 requests anyway....)

Enclosed is my C implementation of Maurer\'s method for Random Bit
Analysis. Anyone using it seriously is *strongly* urged to read the
original article. I have composited several constants, and the significance
of others should be clearly understood before the code is used. Indeed
Maurer describes a whole family of tests: this implements just one.

In the example program, the test is being applied to the least significant 
bit generated by the C rand() function. This will almost certainly fail
the test (my UNIX implementation goes 0101010101010101010.....). A Blum-
Blum-Shub generator should of course pass with flying colours (useful
for calibration)

The test as implemented consumes a lot of output, and so takes a while to
run. As with all statistical tests, the more data, the more confident the 
prognosis. However this data need not be stored.  

The absolute GOOD/BAD indicator should not be taken too seriously. The usual
caveats associated with all statistical testing apply.


Mike Scott
#endif

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/* Maurer's Universal test for Random bits     *
 * Journal of Cryptology, Vol. 5 1992 pp89-105 */

#define Q 10000       /* > 3000   */
#define K 1000000L    /* > 100*Q  */
#define MEAN 7.1836656
#define DEVIATION 1.5*sqrt(3.238/(double)K)

int maurer(gen)
int (*gen)();
{ /* Universal Test for Randomness */
    double sum,ftu;
    int i; long n;
    static long tab[256];
    for (i=0;i<256;i++) tab[i]=(-1);
    for (n=0;n<Q;n++)   tab[(*gen)()]=n;
    /* check each byte occurred at least once */
    for (i=0;i<256;i++) if (tab[i]<0) return 0;
    sum=0.0;
    for (n=Q;n<Q+K;n++)
    { /* scan byte sequence */
        i=(*gen)();
        sum+=log((double)n-tab[i]);
        tab[i]=n;
    }
    ftu= ((sum/(double)K)/log(2.0));
/*    printf("ft= %lf DEV= %lf\n",ftu-MEAN,DEVIATION); */
    if (ftu>(MEAN+DEVIATION) || ftu<(MEAN-DEVIATION)) return 0;
    return 1;
}

static int count = 0;

int generator()
{ /* random bit generator. Pack bits into byte */ 
#if 0
    int i,x;
    for (x=0,i=0;i<8;i++)
        x |= ((rand()&1)<<i);  
    return x;
 /*   return (rand()&255);   */
#else
    count++;
    return(getc(stdin));
#endif
}

main()
{ /* test bit generator for randomness */
    if (maurer(generator)) 
         printf("This seems to be a GOOD random bit generator\n");
    else printf("This is a BAD random bit generator\n");
    printf("I need %d bytes of input\n",count);
} 


