Cómo generar bytes aleatorios altamente impredecibles

1
void
 vncRandomBytes(unsigned char *bytes)
{
int i;
unsigned int seed = (unsigned int) time(0) + getpid() + rand();

srand(seed);
for (i = 0; i < CHALLENGESIZE; i++) {
    bytes[i] = (unsigned char)(rand() & 255);    
}
}

¿Puede el código anterior considerar un generador de cadenas aleatorio seguro?

    
pregunta user236501 18.01.2013 - 18:25
fuente

2 respuestas

7

No, lo siento, tu generador es muy malo. Lo siembran con valores que no tienen mucha entropía (el PID se ajusta a 16 bits ...) o son altamente adivinables (la "hora actual" no es exactamente un valor secreto, todos pueden saberlo con notable exactitud). Y se sabe que el generador que se oculta bajo rand() es rompible (depende del sistema operativo real, pero muchos sistemas usan un generador congruente lineal que puede invertirse fácilmente).

Obtendrá algo que vagamente parece aleatorio a primera vista, pero no resistirá los intentos exitosos de descifrarlo, es decir, predecir la salida futura del generador. Resistir los intentos de craqueo de los atacantes inteligentes es de lo que se trata la seguridad. Sin embargo, su generador podría ser apropiado para algunos usos no relacionados con la seguridad (aunque se sabe que rand() también es bastante malo en estos).

Para la correcta generación de números aleatorios, necesitas:

  1. una semilla inicial con suficiente entropía;
  2. un PRNG criptográficamente seguro que expandirá esa semilla en una larga serie de bytes que serán indistinguibles de la aleatoriedad (incluso ante los ojos de un individuo inteligente y poderoso con grandes computadoras que tiene la intención de predecir el siguiente byte aleatorio).

La semilla inicial debe provenir de algunos eventos de hardware (aleatoriedad "física"), porque el software es, hasta el nivel de transistor, determinista. El sistema operativo está en una posición ideal para reunir eventos físicos (después de todo, ese es su trabajo). Por lo tanto, utilizar el sistema operativo. Esto significa:

  • En sistemas similares a Unix (como Linux, FreeBSD, Solaris, MacOS X ...), use /dev/urandom ( no /dev/random ; consulte esta respuesta para más detalles).
  • En Windows (Win32), llame a CryptGenRandom() .
  • En Java, usa java.security.SecureRandom .
  • En .NET, use System.Security.Cryptography.RNGCryptoServiceProvider .
respondido por el Thomas Pornin 18.01.2013 - 19:14
fuente
3

Lamentablemente, esto no generará material de alta entropía. Casi cualquier tipo de generación pseudoaleatoria en software (como rand() ) no será adecuada para generar bytes aleatorios de buena calidad.

La mayoría de los sistemas operativos vienen con algún tipo de flujo de entropía máximo, respaldado por hardware generador de entropía. Por ejemplo, /dev/random en máquinas basadas en Unix. La lectura de ese flujo es lo más cerca posible de acercarse a 1 bit de entropía por bit de datos.

Editar: Mis estimados colegas han señalado que el uso de /dev/urandom es aceptable para la generación de bytes de alta entropía. No se bloquea de la forma en que lo hace /dev/random , por lo que se desempeña infinitamente mejor si necesita generar una gran cantidad de bytes.

    
respondido por el lynks 18.01.2013 - 18:33
fuente

Lea otras preguntas en las etiquetas