/****************************************************************************/
/* Verifica los tests especificados en FIPS 140.2 (Nov. 1999) */
/* (FEDERAL INFORMATION PROCESSING STANDARD PUBLICATION) */
/* para generadores de números aleatorios. */
/* */
/* Jaime Suarez <[email protected]> 2003 */
/* en http://www.matematicas.net */
/****************************************************************************/
#define LONGBUF 2500 /* 2500 bytes=20000 bits no modificar */
#define BIT(x,n) ( ((x) >> (n)) & 1)
#define HNIB(x) (((x)>>4)&0xF)
#define LNIB(x) ((x)&0xF)
#include <stdio.h>
typedef unsigned char uchar;
int monobit(uchar *buffer);
int poker(uchar *buffer);
int runs(uchar *buffer);
int longrun(uchar *buffer);
main(int argc, char *argv[])
{
uchar buffer[LONGBUF];
FILE *fi;
if (argc<2) {
printf("Uso: %s <fichero>\n",argv[0]);
printf("tests estadísticos de aleatoriedad del fichero.\n");
return 1;
}
if ((fi=fopen(argv[1],"r"))==NULL) {
printf("Error: no puedo abrir %s\n",argv[1]);
return 1;
}
if (fread((void *)buffer,LONGBUF,1,fi) != 1) {
printf("Error leyendo %d bytes de %s.\n",LONGBUF,argv[1]);
fclose(fi);
return 1;
}
fclose(fi);
printf("Fichero: %s\n",argv[1]);
printf("Test monobit: %s ",(monobit(buffer))? "FALLO" : "ok");
printf("Test poker: %s ",(poker(buffer))? "FALLO" : "ok");
printf("Test runs: %s ",(runs(buffer))? "FALLO" : "ok");
printf("Test longrun: %s\n",(longrun(buffer))? "FALLO":"ok");
return 0;
}
/*
* Comprueba si el número de bits iguales a uno está dentro de unos límites
*/
int monobit(uchar *buffer)
{
int unos=0,i,j;
uchar ch;
for (i=0; i<LONGBUF; i++)
for (j=0; j<8; j++)
if (BIT(*(buffer+i),j)) unos++;
if (9725<unos && unos<10275) return 0; /* Ok, error de 0.0001 */
else return 1;
}
/*
* Divididos los 20000 bytes en grupos de 4 consecutivos, se analiza si
* los 16 resultados posibles (0000,0001,...1111) están repartidos
* "regularmente".
*/
int poker(uchar *buffer)
{
int f[16],i;
uchar ch;
float x;
for (i=0; i<16; i++) f[i]=0;
for (i=0; i<LONGBUF; i++) {
ch=*(buffer+i);
f[HNIB(ch)]++;
f[LNIB(ch)]++;
}
x=0.0;
for (i=0; i<16; i++)
x += f[i]*f[i];
x = (x*16.0/5000.0)-5000.0;
if (2.16< x && x<46.17) return 0; /* Nivel de error 0.0001 */
else return 1;
}
/*
* Este test estudia si las secuencias de 1s y 0s repetidos tienen las
* longitudes esperadas.
*/
int runs(uchar *buffer)
{
int i,j,cuenta;
int r[6][2];
uchar ch;
for(i=0; i<6; i++) {
r[i][0]=0;
r[i][1]=0;
}
ch=BIT(*buffer,0);
cuenta=0;
for (i=0; i<LONGBUF; i++) {
for (j=0; j<8; j++) {
if (BIT(*(buffer+i),j)==ch) cuenta++;
else {
if (cuenta>6) cuenta=6;
r[cuenta-1][ch]++;
ch = !ch;
cuenta=1;
}
}
}
if (cuenta>6) cuenta=6;
r[cuenta-1][ch]++;
for (i=0; i<2; i++) {
if (r[0][i]<2343 || r[0][i]>2657) return 1;
if (r[1][i]<1135 || r[1][i]>1365) return 1;
if (r[2][i]< 542 || r[2][i]> 708) return 1;
if (r[3][i]< 251 || r[3][i]> 373) return 1;
if (r[4][i]< 111 || r[4][i]> 201) return 1;
if (r[5][i]< 111 || r[5][i]> 201) return 1;
}
return 0;
}
/*
* Para pasar este test, en los 20000 bits no debe haber una secuencia de
* 26 bits o más iguales consecutivos.
*/
int longrun(uchar *buffer)
{
int i,j,maxc=-1,cuenta;
uchar ch;
ch=BIT(*buffer,0);
cuenta=0;
for (i=0; i<LONGBUF; i++) {
for (j=0; j<8; j++) {
if (BIT(*(buffer+i),j)==ch) cuenta++;
else {
if (cuenta>maxc) maxc=cuenta;
ch=!ch;
cuenta=1;
}
}
}
if (cuenta>maxc) maxc=cuenta;
if (maxc>=26) return 1;
else return 0;
}