Generadores Aleatorios: Cómo Funcionan y Cuándo Usarlos
· 13 min de lectura
Los generadores aleatorios están en todas partes. Cada vez que mezclas una lista de reproducción, generas una contraseña, ejecutas una simulación o juegas un videojuego, un generador de números aleatorios está trabajando detrás de escena. Pero, ¿alguna vez te has preguntado cómo las computadoras — máquinas deterministas que siguen instrucciones exactas — producen aleatoriedad? La respuesta es más fascinante (y más matizada) de lo que podrías esperar.
Esta guía explora la ciencia y la ingeniería detrás de los generadores aleatorios. Cubriremos la diferencia entre números verdaderamente aleatorios y pseudo-aleatorios, cómo funcionan los algoritmos populares, cuándo necesitas aleatoriedad de grado criptográfico y aplicaciones prácticas que afectan tu vida diaria. Ya seas un desarrollador eligiendo la función aleatoria correcta, un estudiante aprendiendo sobre probabilidad, o simplemente curioso sobre cómo funcionan las cosas, esta guía te tiene cubierto.
¿Qué es la Aleatoriedad? Una Mirada Más Profunda
La aleatoriedad parece intuitiva — es imprevisibilidad, caos, la ausencia de patrón. Pero definir la aleatoriedad con precisión es sorprendentemente difícil, y los matemáticos lo han debatido durante siglos.
En el sentido más estricto, una secuencia es verdaderamente aleatoria si ningún algoritmo puede predecir el siguiente valor mejor que adivinando, incluso con conocimiento completo de todos los valores anteriores. Esto se llama aleatoriedad de Kolmogorov — una secuencia es aleatoria si no puede ser comprimida a una descripción más corta. Los dígitos de pi, por ejemplo, pasan todas las pruebas estadísticas de aleatoriedad, sin embargo son completamente deterministas (puedes calcular cualquier dígito con suficiente computación).
Para propósitos prácticos, nos importan tres propiedades de la aleatoriedad:
- Distribución uniforme: Cada resultado posible tiene una probabilidad igual de ocurrir.
- Independencia: Cada valor no está relacionado con valores anteriores o futuros.
- Imprevisibilidad: Un observador no puede predecir el siguiente valor a partir del historial.
Diferentes aplicaciones requieren diferentes niveles de estas propiedades. Un juego de lanzamiento de dados necesita uniformidad e independencia, pero no necesariamente imprevisibilidad. Un generador de contraseñas necesita las tres. Entender qué tipo de aleatoriedad requiere tu aplicación es el primer paso para elegir el generador correcto.
Aleatorio Verdadero vs. Pseudo-Aleatorio: La División Fundamental
Todos los generadores aleatorios caen en dos categorías, y la distinción importa enormemente tanto para la corrección como para la seguridad.
Generadores de Números Verdaderamente Aleatorios (TRNGs)
Los generadores verdaderamente aleatorios derivan la aleatoriedad de fenómenos físicos que son fundamentalmente impredecibles:
- Desintegración radiactiva: El momento exacto en que un átomo emite una partícula es genuinamente impredecible según la mecánica cuántica.
- Ruido atmosférico: Random.org usa receptores de radio para capturar ruido electromagnético atmosférico, que es caótico y no reproducible.
- Ruido térmico: Los componentes electrónicos generan fluctuaciones de voltaje aleatorias debido al movimiento térmico de los electrones.
- Detección de fotones: El tiempo exacto de llegada y la trayectoria de fotones individuales que pasan a través de un divisor de haz es cuánticamente aleatorio.
- RNGs de hardware: Las CPUs modernas (RDRAND de Intel, el equivalente de AMD) incluyen circuitos integrados que recolectan ruido electrónico para generar bits aleatorios.
La propiedad clave de los TRNGs es que su salida es no reproducible. Incluso con equipo y condiciones idénticas, obtendrás secuencias diferentes cada vez. Esto es esencial para aplicaciones criptográficas donde la reproducibilidad sería un fallo fatal.
Generadores de Números Pseudo-Aleatorios (PRNGs)
Los PRNGs son algoritmos — fórmulas matemáticas deterministas que producen secuencias de números que parecen aleatorios pero son completamente predecibles dado el estado inicial (llamado la semilla). Dale a un PRNG la misma semilla, y produce exactamente la misma secuencia cada vez.
Esto puede sonar como una debilidad, pero en realidad es una característica para muchas aplicaciones:
- Reproducibilidad: Los científicos pueden reproducir simulaciones exactamente registrando la semilla.
- Velocidad: Los PRNGs son órdenes de magnitud más rápidos que los TRNGs.
- Sin hardware especial: Los PRNGs se ejecutan en cualquier computadora.
- Capacidad de prueba: Los desarrolladores pueden depurar programas con semillas fijas, asegurando comportamiento consistente.
El desafío es diseñar PRNGs cuya salida sea estadísticamente indistinguible de la aleatoriedad verdadera — pasando todas las pruebas estadísticas conocidas de uniformidad, independencia y falta de patrón.
🎲 Prueba nuestros generadores
Cómo Funcionan los Generadores de Números Pseudo-Aleatorios (PRNGs)
En su núcleo, los PRNGs mantienen un estado interno que transforman con cada llamada, produciendo una salida y actualizando el estado para la próxima vez. La calidad de un PRNG depende de qué tan bien su transformación evita patrones y correlaciones.
Generador Congruencial Lineal (LCG)
La familia de PRNGs más simple y antigua, los LCGs usan la fórmula:
estado = (a × estado + c) mod m
salida = estado
Donde a (multiplicador), c (incremento), y m (módulo) son constantes cuidadosamente elegidas. Por ejemplo, el generador clásico MINSTD usa a = 16807, c = 0, m = 2³¹ - 1. Los LCGs son increíblemente rápidos (una multiplicación y un módulo) pero tienen debilidades bien conocidas: los valores secuenciales muestran patrones cuando se grafican en dimensiones superiores, y los bits de orden bajo ciclan con períodos cortos. La mayoría de las aplicaciones modernas han superado los LCGs.
Mersenne Twister (MT19937)
El Mersenne Twister ha sido el PRNG predeterminado en muchos lenguajes y sistemas desde su introducción en 1997. Mantiene un estado de 624 enteros de 32 bits y tiene un período de 2¹⁹⁹³⁷ - 1 (un primo de Mersenne, de ahí el nombre). Ese período es astronómicamente largo — mucho más que el número de átomos en el universo observable.
El algoritmo funciona mediante:
- Inicializar 624 valores de estado desde una semilla
- Para cada número aleatorio, extraer y "templar" un valor de estado a través de desplazamientos de bits y operaciones XOR
- Regenerar periódicamente todo el arreglo de estado usando una transformación de torsión
Mersenne Twister pasa la mayoría de las pruebas estadísticas y es excelente para simulaciones, juegos y uso general. Sin embargo, no es criptográficamente seguro — observar 624 salidas permite reconstruir el estado interno completo y predecir todos los valores futuros.
Xoshiro256** y PRNGs Modernos
Los PRNGs más nuevos como xoshiro256** (usado en muchos lenguajes modernos) y PCG (Generador Congruencial Permutado) abordan las deficiencias de los generadores más antiguos. Ofrecen:
- Estado más pequeño (256 bits vs. 20 KB para Mersenne Twister)
- Mejores propiedades estadísticas en casos extremos
- Ejecución más rápida con operaciones de una sola instrucción
- Estado saltable (saltar adelante en la secuencia sin generar valores intermedios)
Math.random() de JavaScript
Cuando llamas a Math.random() en JavaScript, los motores modernos (V8, SpiderMonkey, JavaScriptCore) usan xorshift128+, un PRNG rápido con buenas propiedades estadísticas. Produce un número de punto flotante entre 0 (inclusivo) y 1 (exclusivo). Aunque perfectamente adecuado para juegos, mezclas y selección aleatoria, nunca debe usarse para propósitos sensibles a la seguridad.
// Número aleatorio básico entre min y max (inclusivo)
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// Elemento aleatorio de un arreglo
function randomChoice(array) {
return array[Math.floor(Math.random() * array.length)];
}
// Mezclar un arreglo (algoritmo Fisher-Yates)
function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
Aleatoriedad Criptográfica: Cuando la Seguridad Importa
Para aplicaciones de seguridad — contraseñas, claves de cifrado, tokens de sesión, nonces — los PRNGs regulares son peligrosamente inadecuados. Un atacante que pueda predecir tus números aleatorios puede comprometer todo tu modelo de seguridad.
¿Qué Hace Diferente a un CSPRNG?
Un Generador de Números Pseudo-Aleatorios Criptográficamente Seguro (CSPRNG) añade una propiedad crítica: secreto hacia adelante y hacia atrás. Incluso si un atacante descubre el estado interno actual, no puede determinar salidas anteriores (secreto hacia atrás). Y predecir salidas futuras a partir de salidas pasadas es computacionalmente inviable sin conocer el estado.
Los CSPRNGs logran esto mediante:
- Estado interno grande: 256+ bits, haciendo impráctica la recuperación del estado por fuerza bruta
- Funciones unidireccionales: La transformación de salida es computacionalmente irreversible
- Resembrado continuo: Mezclar regularmente entropía fresca de fuentes de hardware
- Destrucción de estado: Sobrescribir estados anteriores después del uso
CSPRNGs Comunes
- ChaCha20: Usado por
/dev/urandomde Linux (desde el kernel 4.8) y muchos sistemas modernos. Rápido, seguro y bien analizado. - AES-CTR-DRBG: Basado en cifrado AES en modo contador. Recomendado por NIST y acelerado por hardware en CPUs modernas.
- Fortuna: Diseñado por Bruce Schneier. Usa múltiples pools de entropía para resistencia contra compromiso parcial.
Usando Aleatoriedad Criptográfica en la Práctica
En el navegador, la API Web Crypto proporciona aleatoriedad de grado criptográfico:
// Generar un entero aleatorio criptográficamente seguro
function secureRandomInt(min, max) {
const range = max - min + 1;
const bytesNeeded = Math.ceil(Math.log2(range) / 8);
const maxValid = Math.floor(256 ** bytesNeeded / range) * range - 1;
let value;
do {
const array = new Uint8Array(bytesNeeded);
crypto.getRandomValues(array);
value = array.reduce((acc, byte, i) => acc + byte * (256 ** i), 0);
} while (value > maxValid); // Rechazar valores sesgados
return min + (value % range);
}
// Generar una contraseña aleatoria segura
function generatePassword(length = 16) {
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*';
const array = new Uint32Array(length);
crypto.getRandomValues(array);
return Array.from(array, x => chars[x % chars.length]).join('');
}
Prueba generar contraseñas seguras con nuestro Generador de Contraseñas, que usa la API Web Crypto para aleatoriedad de grado criptográfico.
Entropía: El Combustible de la Aleatoriedad
La entropía, en el contexto de la aleatoriedad, mide la cantidad de imprevisibilidad genuina en un sistema. Se mide en bits — un bit de entropía significa una elección binaria que un atacante no puede predecir.
¿De Dónde Viene la Entropía?
Los sistemas operativos recolectan continuamente entropía de múltiples fuentes:
- Temporización de teclado y ratón: Los intervalos exactos a nivel de microsegundos entre pulsaciones de teclas y movimientos del ratón son impredecibles.
- Temporización de E/S de disco: Los tiempos de búsqueda y temporización de interrupciones tienen jitter inherente de factores mecánicos y electrónicos.
- Temporización de paquetes de red: Los tiempos de llegada de paquetes de red incluyen variaciones de submicrosegundos de las condiciones de red.
- RNG de hardware: Las CPUs modernas proporcionan fuentes de entropía dedicadas (Intel RDRAND/RDSEED, ARM RNDR).
- Ruido de sensor térmico: Las lecturas de temperatura a máxima p