Aleatoriedad criptográfica en la generación de contraseñas
Lectura de 8 min aprox.
El factor más importante que determina la seguridad de un generador de contraseñas es la calidad de los números aleatorios que utiliza. Aunque una cadena parezca aleatoria, si los números aleatorios utilizados en su generación son predecibles, un atacante puede adivinar la contraseña. NIST SP 800-90A es el estándar que define los requisitos para generadores de números aleatorios criptográficos, y los números aleatorios utilizados para la generación de contraseñas deben cumplir este estándar. A partir de 2025, con el avance de la computación cuántica, NIST está avanzando en la estandarización de criptografía post-cuántica (PQC), y los criterios de seguridad para la generación de números aleatorios podrían revisarse en el futuro. Este artículo explica técnicamente los tipos y diferencias de calidad de los números aleatorios, y describe el método seguro de generación adoptado por Passtsuku.com. Comprender esto junto con el concepto de entropía de contraseñas revela la esencia de la fortaleza de las contraseñas.
El peligro de Math.random()
La forma más sencilla de generar números aleatorios en JavaScript es `Math.random()`. Sin embargo, esta función nunca debe usarse para la generación de contraseñas. `Math.random()` es un generador de números pseudoaleatorios (PRNG) que genera secuencias numéricas de forma determinista a partir de un estado interno (valor semilla).
Los problemas específicos de `Math.random()` son los siguientes:
- Estado interno predecible: el estado interno puede deducirse a partir de la secuencia de salida
- Sin garantía de seguridad criptográfica: la especificación ECMAScript no garantiza nada sobre la calidad de la aleatoriedad
- La implementación varía según el navegador: el motor V8 (Chrome) usa el algoritmo xorshift128+, inadecuado para fines criptográficos
- Predicción de semilla: algunas implementaciones usan marcas de tiempo como semilla, por lo que si se conoce el momento de generación, la salida puede reproducirse
Investigadores de seguridad han demostrado métodos de ataque que recuperan el estado interno a partir de la salida de `Math.random()`. Una investigación publicada en 2015 mostró que para la implementación xorshift128+ del motor V8, el estado interno podía recuperarse completamente con solo 64 valores de salida consecutivos. Las contraseñas generadas con `Math.random()` pueden parecer aleatorias, pero para los atacantes son simplemente cadenas predecibles.
Un punto que a menudo se pasa por alto es que `Math.random()` produce números de punto flotante entre 0 (inclusive) y 1 (exclusive), usando internamente solo 52 bits de mantisa. Esto significa que el número máximo de valores posibles es 2^52 (aproximadamente 4.5 × 10^15). Dado que las aplicaciones criptográficas requieren 128 bits o más de entropía, `Math.random()` por sí solo es fundamentalmente insuficiente en cantidad de bits.
Cómo funciona CSPRNG
Los números aleatorios adecuados para la generación de contraseñas deben producirse mediante un Generador de Números Pseudoaleatorios Criptográficamente Seguro (CSPRNG). Un CSPRNG satisface las siguientes dos propiedades:
- Impredecibilidad: incluso conociendo todas las salidas anteriores, no se puede predecir la siguiente
- Irreversibilidad: es computacionalmente inviable deducir el estado interno a partir de la salida
Un CSPRNG utiliza fuentes de entropía recopiladas por el sistema operativo como semilla. Las fuentes de entropía incluyen eventos físicamente impredecibles como el ruido eléctrico del hardware, movimientos del ratón, temporización de entrada del teclado y temporización de E/S de disco. Al procesar estos datos impredecibles mediante funciones hash criptográficas y cifrados de bloque, se generan secuencias de números aleatorios de alta calidad.
Linux proporciona `/dev/urandom` y Windows proporciona BCryptGenRandom como CSPRNGs a nivel de sistema operativo. Estas son implementaciones confiables con años de auditoría de seguridad y trayectoria comprobada. Para los fundamentos teóricos de la generación de números aleatorios criptográficos, libros sobre CSPRNG y diseño de seguridad criptográfica (Amazon) también son útiles.
Web Crypto API: crypto.getRandomValues()
La forma estándar de usar un CSPRNG en entornos de navegador es `crypto.getRandomValues()` de la Web Crypto API. Esta API está estandarizada por el W3C y está disponible en todos los navegadores modernos.
`crypto.getRandomValues()` llama directamente al CSPRNG proporcionado por el sistema operativo para generar números aleatorios. Esto significa que se obtienen números aleatorios criptográficamente seguros verificados a nivel del sistema operativo, no un algoritmo específico del navegador.
La diferencia decisiva con `Math.random()` es que `crypto.getRandomValues()` garantiza seguridad criptográfica. Es computacionalmente inviable inferir el estado interno a partir de la salida, y conocer las salidas pasadas no permite predecir las futuras.
Sin embargo, `crypto.getRandomValues()` tiene restricciones. El número máximo de bytes que se pueden obtener en una sola llamada está limitado a 65,536 bytes, y las solicitudes que excedan este límite lanzarán una excepción. Es poco probable alcanzar este límite para la generación de contraseñas, pero se debe tener precaución para usos de simulación que requieran grandes cantidades de números aleatorios.
Como método para verificar la calidad de los números aleatorios, el conjunto de pruebas estadísticas definido por NIST SP 800-22 es ampliamente utilizado. Este conjunto incluye 15 tipos de pruebas, incluyendo pruebas de frecuencia, pruebas de rachas y pruebas de complejidad lineal. La salida de `crypto.getRandomValues()` pasa todas estas pruebas, mientras que la salida de `Math.random()` es conocida por fallar en múltiples pruebas. Para métodos de evaluación de calidad de números aleatorios, libros sobre pruebas de aleatoriedad NIST y evaluación criptográfica (Amazon) también son útiles.
Método de generación de números aleatorios de Passtsuku.com
Passtsuku.com utiliza `crypto.getRandomValues()` para todos los pasos de la generación de contraseñas. `Math.random()` nunca se usa. Esto garantiza que cada carácter de la contraseña generada se selecciona basándose en números aleatorios criptográficamente seguros.
Garantía de distribución uniforme
Además de la calidad de los números aleatorios, Passtsuku.com también asegura la uniformidad en la selección de caracteres. Si los valores devueltos por `crypto.getRandomValues()` simplemente se toman módulo el tamaño del conjunto de caracteres, se produce un ligero sesgo cuando el tamaño no es una potencia de 2. Por ejemplo, cuando números aleatorios en el rango 0-255 se toman módulo un conjunto de 62 caracteres (mayúsculas + minúsculas + dígitos), los primeros 8 caracteres se seleccionan con aproximadamente 1.6% más de probabilidad. Passtsuku.com emplea muestreo por rechazo para eliminar este sesgo, asegurando que todos los caracteres se seleccionen con probabilidad perfectamente igual.
Seguridad completamente en el navegador
La generación de números aleatorios y contraseñas de Passtsuku.com se completa enteramente dentro del navegador. Las contraseñas generadas y los valores semilla nunca se transmiten externamente a través de la red. Como no hay procesamiento del lado del servidor, el riesgo de interceptación en la ruta de comunicación es cero.
Al elegir una herramienta de generación de contraseñas, es importante verificar qué método de generación de números aleatorios utiliza. Las herramientas que usan `Math.random()` tienen preocupaciones de seguridad, así que elija una herramienta como Passtsuku.com que usa `crypto.getRandomValues()`.
Lista de verificación de calidad de números aleatorios
Al elegir una herramienta de generación de contraseñas, verifique la calidad de los números aleatorios desde las siguientes perspectivas:
- Si la herramienta usa `crypto.getRandomValues()` o un CSPRNG equivalente
- Si se declara explícitamente que no se usa `Math.random()`
- Si el proceso de generación se completa dentro del navegador (lado del cliente)
- Si se utilizan técnicas de eliminación de sesgo como el muestreo por rechazo para la selección de caracteres
- Si el código fuente es público y el método de generación de números aleatorios puede verificarse
Passtsuku.com cumple todas estas condiciones. Al comprender el concepto de entropía y la relación con las funciones hash, puede obtener una comprensión más profunda de cómo la calidad de los números aleatorios afecta la fortaleza de las contraseñas. Para orientación práctica sobre la aplicación de estos principios, consulte cómo crear contraseñas seguras y los fundamentos de cifrado. Los números aleatorios de alta calidad son lo que hace que las contraseñas sean resistentes a los ataques de fuerza bruta.
Actúa ahora
- Genera una contraseña de 16 caracteres o más con Passtsuku.com y reemplaza tus contraseñas creadas manualmente
- Verifica que tu herramienta actual de generación de contraseñas use crypto.getRandomValues() (o un CSPRNG equivalente)
- Usa el medidor de fortaleza de Passtsuku.com para confirmar que las contraseñas generadas tienen 80 bits o más de entropía
- Actualiza tu navegador a la última versión para asegurar el acceso a la implementación más reciente de la Web Crypto API
Preguntas frecuentes
- ¿Es seguro generar contraseñas con Math.random()?
- No, no es seguro. Math.random() no es un generador de números aleatorios criptográficamente seguro y sus patrones de salida son predecibles. Usa crypto.getRandomValues() de la Web Crypto API para generar contraseñas.
- ¿Cuál es la diferencia entre números aleatorios criptográficamente seguros y regulares?
- Los números pseudoaleatorios regulares están determinados por un valor semilla, por lo que conocer la semilla revela todas las salidas. Los números aleatorios criptográficamente seguros usan fuentes de entropía de hardware, haciendo computacionalmente inviable predecir salidas futuras a partir de las pasadas.
- ¿Cómo puedo verificar la calidad de los números aleatorios de un generador de contraseñas?
- Para herramientas de código abierto, verifica si usan APIs criptográficamente seguras como crypto.getRandomValues() o /dev/urandom. Para herramientas de código cerrado, puedes verificar estadísticamente generando muchas contraseñas y comprobando el sesgo en la frecuencia de caracteres.
¿Te resultó útil este artículo?