/****************************************************************************/ /* Verifica los tests especificados en FIPS 140.2 (Nov. 1999) */ /* (FEDERAL INFORMATION PROCESSING STANDARD PUBLICATION) */ /* para generadores de números aleatorios. */ /* */ /* Jaime Suarez <mcripto@bigfoot.com> 2003 */ /* en http://elparaiso.mat.uned.es */ /****************************************************************************/ #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; }