Parte: 2 — Criptografía aplicada · Fuente: Serious Cryptography (Aumasson) y NIST SP 800-90A ⏱️ Duración estimada: 90 min · Nivel: Intermedio
Comprender por qué la aleatoriedad es el cimiento silencioso de toda la criptografía: claves, nonces, IVs, salts y tokens dependen de ella. El alumno aprenderá la diferencia entre un PRNG estadístico (predecible) y un CSPRNG (criptográficamente seguro), de dónde viene la entropía del sistema operativo, y por qué fallos de aleatoriedad han roto sistemas reales (Debian OpenSSL 2008, claves RSA con primos compartidos).
Al finalizar, el alumno podrá:
secrets, os.urandom).random para seguridad.| # | Tema | Por qué importa |
|---|---|---|
| 1 | Entropía y fuentes | Origen de la aleatoriedad |
| 2 | PRNG vs CSPRNG | Predecible vs seguro |
| 3 | /dev/urandom y getrandom() | API del SO |
| 4 | DRBG (SP 800-90A) | Generadores deterministas seguros |
| 5 | APIs seguras (secrets) |
Uso correcto en código |
| 6 | Fallos famosos | Aprender de desastres |
| 7 | Pruebas de aleatoriedad | Detectar sesgos |
python3 -c "import secrets; print('ok')"
# opcional: pruebas estadísticas
which rngtest dieharder 2>/dev/null || echo "opcional"
Todo el trabajo es local y de análisis.
python
import os, secrets
clave = os.urandom(32) # 256 bits para AES
nonce = os.urandom(12) # nonce GCM
token = secrets.token_urlsafe(32) # token de sesión
print(clave.hex(), token)
Contraejemplo predecible. Muestra que random.seed(tiempo) + random.getrandbits produce salidas reproducibles si el atacante conoce el instante; concluye que random no sirve para seguridad.
Analiza sesgos. Genera 1 MB con un CSPRNG y con un PRNG mal sembrado; corre pruebas estadísticas (o cuenta frecuencias de bits) y compara.
Estudia el fallo Debian 2008. Investiga cómo un parche que redujo la entropía dejó el espacio de claves en apenas ~32.767 posibilidades y por qué hubo que regenerar millones de claves.
Nonces únicos. Simula la generación de nonces para AES-GCM y verifica (con un conjunto) que no se repiten en el volumen esperado.
random y secrets en Python.time() produce salidas predecibles.Escribe una utilidad que genere claves, nonces y tokens exclusivamente con un CSPRNG, y un test que verifique ausencia de repeticiones en una gran muestra de nonces y una distribución de bits cercana a 50/50. Criterio de aceptación: la muestra no presenta nonces repetidos y la proporción de unos/ceros se desvía menos de un umbral razonable; el código no usa ningún PRNG estadístico.
| Síntoma / mensaje | Causa y cómo arreglar |
|---|---|
| Claves reproducibles | Semilla predecible; usa os.urandom/secrets |
Uso de random/rand() para claves |
No es CSPRNG; sustitúyelo |
| Nonces repetidos | Generación insegura; usa CSPRNG o contador único |
| Baja entropía en arranque | Bloquea hasta sembrar (getrandom) o añade fuente de hardware |
| Reutilizar tokens de sesión | Genera uno nuevo por sesión con suficiente longitud |
❓ ¿/dev/urandom o /dev/random?
En Linux moderno, urandom/getrandom() es la elección correcta una vez sembrado; random puede bloquear innecesariamente.
❓ ¿Cuántos bits necesito para un token? Al menos 128 bits (16 bytes) de aleatoriedad real; 256 bits para márgenes amplios.
❓ ¿Por qué la mala aleatoriedad es tan peligrosa? Porque compromete claves y nonces de golpe; un CSPRNG débil hace inútil el mejor algoritmo.
Clase 057 — Almacenamiento seguro de contraseñas: bcrypt, scrypt y Argon2