/****************************************************************************/ /* Algoritmo de Blum-Blum-Shub para generación de números pseudoaleatorios. */ /* */ /* Jaime Suarez <mcripto@bigfoot.com> 2003 */ /* en http://elparaiso.mat.uned.es */ /****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "gmp.h" /* Este es el tamaño aproximado del módulo n */ #define BITS_MODULO 1024 /* Inicializa el generador de números aleatorios, s es una cadena con un * número en base 10 que sirve de semilla. Es importante que sea lo más * aleatorio posible y de un tamaño similar al de n */ void iniciarBBS(char *s); /* Devuelve un bit aleatorio de un generador ya inicializado */ int bitBBS(void); /* Devuelve un byte aleatorio de un generador BBS ya inicializado */ int byteBBS(void); /* * Comienzo del programa */ int main(int argc, char *argv[]) { int i, nBytes; unsigned char s[256]; FILE *fo; if (argc!=3) { printf("------------------------------------------------------\n"); printf(" Generador de números pseudoaleatorios Blum-Blum-Shub.\n\n"); printf(" Uso: %s <n> <s>\n",argv[0]); printf(" n: numero de bytes deseados.\n"); printf(" s: semilla, cadena de caracteres arbitrarios.\n"); printf("------------------------------------------------------\n"); return 1; } /* Leer línea de comandos */ nBytes=atoi(argv[1]); strncpy(s,argv[2],256); /* Convertir la cadena s en un entero */ for (i=0; i<strlen(s); i++) s[i]=(s[i]%10)+'0'; /* Inicializa generador y produce los bytes pedidos * guardándolos en bbs.out */ iniciarBBS(s); fo = fopen("bbs.out", "wb"); for (i=0; i<nBytes; i++) { fprintf(fo, "%c", byteBBS()); } fclose(fo); puts("Resultados en el fichero: bbs.out"); return 0; } mpz_t x; /* Último valor aleatorio */ mpz_t n; /* Módulo para BBS */ /* * Inicia el generador de numeros aleatorios a partir de la cadena s * que contiene un entero en base 10 que sirve como semilla. */ void iniciarBBS(char *s) { mpz_t p, q, tmp; gmp_randstate_t estado; /* Inicializar rng de la librería gmp3 */ gmp_randinit_default(estado); mpz_set_str(tmp, s, 10); gmp_randseed(estado, tmp); /* Inicializar enteros largos */ mpz_init(x); mpz_init(n); mpz_init(p); mpz_init(q); /* Tenemos que generar n como producto * de dos grandes primos congruentes con 3 modulo 4 */ do { mpz_urandomb(p, estado, BITS_MODULO/2); mpz_mul_ui(p,p,4); mpz_add_ui(p,p,3); } while (mpz_probab_prime_p(p,25)==0); do { mpz_urandomb(q, estado, BITS_MODULO/2); mpz_mul_ui(q,q,4); mpz_add_ui(q,q,3); } while (mpz_probab_prime_p(q,25)==0); mpz_mul(n,p,q); /* Ahora se produce la primera x = s^2 (mod n) */ mpz_set_str(x,s,10); mpz_mod(x,x,n); mpz_mul(x,x,x); mpz_mod(x,x,n); /* Limpiamos variables innecesarias en lo sucesivo */ mpz_clear(p); mpz_clear(q); return; } /* */ /* Genera un bit pseudoaleatorio a partir de la variable global x */ /* previamente existente. Es necesario llamar a iniciarBBS antes de */ /* utilizarlo. */ int bitBBS(void) { mpz_mul(x,x,x); mpz_mod(x,x,n); /* x = x^2 mod n */ return mpz_tstbit(x, 0); /* devolver el bit menos significativo */ } /* * Devuelve un byte pseudoaleatorio. Debe llamarse una vez a iniciarBBS * antes de comenzar a pedir bytes. */ int byteBBS(void) { int byte=0, i; for (i=0; i<8; i++) byte = byte*2 + bitBBS(); return byte; }