La respuesta simple es que si no confías en CryptGenRandom()
, estás condenado. De hecho, CryptGenRandom()
es provisto por el sistema operativo, y si el sistema operativo es hostil, hay muy poco que puedas hacer para defenderte de él. Un sistema operativo hostil puede inspeccionar toda su RAM, registrar todas sus contraseñas, enviar todos sus datos a terceros externos.
La respuesta menos simple se basa en una sutileza, que es que puede desconfiar de CryptGenRandom()
y no suponer que el sistema operativo sea hostil. Tal vez considere que CryptGenRandom()
es simplemente defectuoso, por accidente y no por malicia, y ofrece aleatoriedad de mala calidad, mientras que ningún otro componente del sistema operativo trata de engañarle.
En ese caso, se vuelve sensible a aumentar CryptGenRandom()
con un poco de entropía adicional. La entropía proviene de eventos físicos y el sistema operativo está idealmente ubicado para reunir eventos físicos; Las aplicaciones están en una posición mucho menos ideal para eso. Sin embargo, algunas personas lo han intentado. Por ejemplo, hay un recolector de entropía aplicativo en GnuPG (al menos en la versión 1.4.14, busque el archivo rndw32.c
).
La forma correcta para reunir entropía es tomar todos los "eventos" (por ejemplo, "la tecla X se presionó en el momento T"), concatenarlos juntos, luego hash todo el lote con una función hash adecuada como SHA-256. Luego use la salida como semilla para un PRNG criptográficamente seguro . En particular, no rechace CryptGenRandom()
completamente; Llámelo para obtener algunos bytes de salida (por ejemplo, 16 bytes) y agregue esa salida como un "evento" como todos los demás que reúne. La belleza del hashing es que incluso si el evento es defectuoso de una manera maliciosa, no puede disminuir su entropía resultante; solo puede contribuir de manera positiva (en el peor de los casos, no aporta cantidades significativas de entropía).
La parte difícil de la generación aleatoria no es obtener entropía; es estimar cuánto tienes. Un evento de hardware es "entropía útil" exactamente en la medida en que cualquier atacante potencial no puede predecir su contenido. Por ejemplo, un atacante que observa la red puede predecir el momento exacto en que su máquina recibe un paquete entrante, con una precisión de, tal vez, del microsegundo. Si cronometra ese evento con una precisión de nanosegundos ( Contadores de sellos de tiempo son convenientes para eso, Windows los llama "contadores de rendimiento") , entonces puede considerar que cada paquete entrante produce 10 bits de entropía (porque 2 10 es aproximadamente igual a 1000, que es la relación entre microsegundos y nanosegundos). Todo es relativo a un contexto físico específico; hacer un RNG de talla única en software puro implica, por lo tanto, una gran cantidad de excesos.