CSPRNG con Web Crypto API: Generación de Entropía
Aprende a generar números y cadenas criptográficamente seguras con Web Crypto API y CSPRNG en navegadores modernos y Node.js en 2026.

La implementación de CSPRNG con Web Crypto API constituye en 2026 el requisito fundamental para el desarrollo seguro de aplicaciones frontend, autenticadores WebAuthn, generadores de credenciales y sistemas de firma digital. A pesar de años de advertencias de los organismos de estandarización, el uso indebido de funciones pseudoaleatorias débiles como Math.random() continúa provocando incidentes de seguridad que permiten la predicción de tokens de restablecimiento de contraseña y claves de sesión.
Un generador de números pseudoaleatorios criptográficamente seguro (CSPRNG) no solo requiere una distribución estadística uniforme, sino el cumplimiento estricto del criterio del siguiente bit (Next-Bit Test): ningún algoritmo computacional debe ser capaz de predecir el bit subsiguiente con una probabilidad mayor al 50%.
Fuentes de Entropía Física y el Motor de Web Crypto API
En navegadores modernos y entornos de ejecución como Node.js y Deno, la interfaz estándar crypto.getRandomValues() y crypto.randomUUID() se comunica directamente con las primitivas criptográficas del kernel del sistema operativo:
- Linux / Android:
/dev/urandomy la syscallgetrandom(), alimentadas por el driver ChaCha20 del kernel. - Windows:
BCryptGenRandomde la biblioteca Cryptography API: Next Generation (CNG). - macOS / iOS:
CCRandomGenerateBytesySecRandomCopyBytes.
Estas fuentes recopilan ruido de eventos no deterministas: fluctuaciones térmicas de los sensores de la CPU, diferencias de tiempo en interrupciones de disco (I/O) y jitter de tramas de red Ethernet/WiFi.
Para generar contraseñas y claves maestras con alta entropía matemática ejecutadas 100% en el cliente, prueba nuestro Generador de Contraseñas Seguras.
Comparativa: PRNG Estándar vs CSPRNG Criptográfico
| Característica de Seguridad | Math.random() (PRNG) |
crypto.getRandomValues() (CSPRNG) |
|---|---|---|
| Algoritmo Subyacente | xorshift128+ / Mulberry32 | ChaCha20 / AES-CTR-DRBG (NIST SP 800-90A) |
| Fuente de Entropía | Semilla estática o timestamp | Ruido físico del kernel del SO |
| Resistencia a Predicción | Nula (predecible en < 10 observaciones) | Criptográficamente invulnerable ($2^{128}$) |
| Resistencia a Compromiso de Estado | Nula | Resiliente (Backtracking Resistance) |
| Uso Permitido | Animaciones visuales, juegos, tests | Tokens de sesión, UUIDs, claves criptográficas |
Implementación de Generación Sin Sesgo (Rejection Sampling) en TypeScript
El error más común al usar crypto.getRandomValues() consiste en aplicar el operador módulo (% max) para restringir el valor a un rango específico, lo que introduce un sesgo de módulo estadístico.
A continuación se muestra la implementación correcta mediante muestreo con rechazo (Rejection Sampling):
/**
* Genera un número entero aleatorio criptográficamente seguro en el rango [0, max - 1]
* sin sesgo de módulo (Modulo Bias).
*/
export function getSecureRandomInt(max: number): number {
if (max <= 0 || max > 0xFFFFFFFF) {
throw new Error('El rango max debe estar entre 1 y 2^32 - 1');
}
const randomBuffer = new Uint32Array(1);
const maxUint32 = 0x100000000; // 2^32
const limit = maxUint32 - (maxUint32 % max); // Umbral de rechazo para eliminar sesgo
let randomValue: number;
do {
crypto.getRandomValues(randomBuffer);
randomValue = randomBuffer[0];
} while (randomValue >= limit);
return randomValue % max;
}
/**
* Genera una cadena alfanumérica segura con entropía verificada
*/
export function generateSecureToken(length: number): string {
const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+';
let token = '';
for (let i = 0; i < length; i++) {
token += charset[getSecureRandomInt(charset.length)];
}
return token;
}
Esta función garantiza que cada carácter del alfabeto tenga exactamente la misma probabilidad matemática de ser seleccionado, maximizando la entropía de Shannon por bit.
Buenas Prácticas de Generación Criptográfica en el Cliente
Para evitar errores de implementación en aplicaciones web:
- Límites de Buffer: Recuerda que
crypto.getRandomValues()impone un límite de 65,536 bytes por llamada para evitar la degradación del pool de entropía. - Generación de Identificadores Únicos: Utiliza
crypto.randomUUID()para generar identificadores RFC 4122 v4 nativos, respaldándote en nuestro Generador de UUID y ULID. - Verificación de Entropía: Evalúa la fuerza matemática de tus credenciales mediante nuestro Verificador de Contraseñas y Entropía.
- Cálculo de Hashes Seguros: Emplea algoritmos resistentes a colisiones analizados en Cálculo y Generación de Hashes SHA-256.
- Autenticación FIDO2: Integra llaves criptográficas de hardware según las pautas de Passkeys y Autenticación Passwordless.
Ataques Reales de Predicción de Estado en Generadores Débiles (PRNG)
Para comprender la severidad del uso indebido de Math.random(), consideremos el algoritmo xorshift128+ empleado históricamente en motores V8 de Chromium. El generador mantiene un estado interno de 128 bits repartido en dos enteros de 64 bits (s[0] y s[1]).
Dado que cada llamada a Math.random() expone directamente los 53 bits superiores del estado resultante en la mantisa del número de punto flotante de doble precisión, un atacante que recopile únicamente 2 o 3 valores consecutivos puede formular un sistema de ecuaciones lineales sobre el cuerpo finito GF(2) y resolver el estado interno completo en menos de 10 milisegundos mediante el algoritmo de eliminación de Gauss.
export async function generateHmacSecretKey(): Promise<CryptoKey> {
return await window.crypto.subtle.generateKey(
{
name: 'HMAC',
hash: { name: 'SHA-256' }
},
true,
['sign', 'verify']
);
}
Auditoría Estadística de Entropía: Baterías de Tests Dieharder y NIST SP 800-22
Para certificar que una rutina de generación cumple con los estándares criptográficos internacionales, las implementaciones se someten a suites de pruebas estadísticas como Dieharder y NIST SP 800-22. Estas pruebas evalúan la frecuencia monobit, las secuencias de rachas y el rango de matrices binarias para descartar cualquier correlación.
Resumen
La aleatoriedad predecible es la causa de incontables brechas de seguridad. Migrar todas las funciones de generación de claves y tokens a crypto.getRandomValues() con algoritmos de muestreo sin sesgo asegura una protección matemática inexpugnable.
Normativas:
- NIST SP 800-90A: Recommendation for Random Number Generation Using Deterministic Random Bit Generators.
- W3C Web Cryptography API Recommendation.
- Análisis TecnoCrypter: Contraseñas Seguras y Entropía Matemática.


