Skip to content

Latest commit

 

History

History
266 lines (181 loc) · 11.3 KB

File metadata and controls

266 lines (181 loc) · 11.3 KB

0x700 — Cryptology

Índice


0x710 — Teoría de la información

Tres conceptos que dan forma a toda la criptografía:

  • Confidencialidad — solo el destinatario lee el mensaje.
  • Integridad — el mensaje no ha sido modificado.
  • Autenticación — el remitente es quien dice ser.

Una primitiva no garantiza las tres. AES-CBC da confidencialidad pero no integridad → necesitas un MAC (HMAC) encima. AES-GCM las da las dos en una sola operación. AEAD (Authenticated Encryption with Associated Data) es el estándar moderno: AES-GCM, ChaCha20-Poly1305.

Entropía

H(X) = -Σ p(x) · log₂(p(x)) — bits de incertidumbre. Una password "password" tiene entropía 0 (todo el mundo la conoce). Una password de 12 caracteres aleatorios [a-zA-Z0-9] tiene 12 · log₂(62) ≈ 71 bits.

Para keys criptográficas: necesitas al menos 128 bits de entropía real para AES-128, 256 para AES-256. Sacarlo de /dev/urandom o getrandom() — nunca de rand() ni de timestamps.

Confusión y difusión (Shannon, 1949)

Un buen cifrado tiene:

  • Confusión: la relación entre key y ciphertext es complicada. Cambiar 1 bit de key cambia ~la mitad de los bits del ciphertext.
  • Difusión: un cambio en 1 bit de plaintext cambia ~la mitad de los bits del ciphertext (avalancha).

AES cumple ambas tras 10/12/14 rondas. Si un cifrado nuevo no muestra avalancha → no es seguro.


0x720 — Tiempo de ejecución (notación O)

La fortaleza de un cifrado se mide en cuántas operaciones tarda romperlo. Notación O resume el crecimiento:

Notación Significado Ejemplo
O(1) constante hash lookup
O(log n) logarítmica búsqueda binaria
O(n) lineal recorrer un array
O(n log n) linearítmica merge sort
O(n²) cuadrática bubble sort
O(2ⁿ) exponencial brute force key
O(n!) factorial TSP por fuerza bruta

Una key de 128 bits implica 2¹²⁸ posibilidades. A 1 billón de pruebas/segundo (10¹²), tarda:

2^128 / 10^12 / 60 / 60 / 24 / 365 = 1.08 × 10^19 años

Por eso AES-128 se considera seguro contra fuerza bruta clásica. Cuántica cambia el cálculo: Grover lo reduce a 2⁶⁴ → AES-256 sí, AES-128 dudoso a 30+ años vista.

Implementaciones

codigo/0x720/timing.c mide cuánto tarda una búsqueda lineal vs binaria sobre arrays de tamaños crecientes.


0x730 — Cifrado simétrico

Misma key para cifrar y descifrar. Rápido, pero el reto es distribuir la key sin que un tercero la vea.

Algoritmo Estado Notas
DES Roto 56 bits, brute-forceable en horas. Sólo legacy.
3DES Deprecado 112 bits efectivos, lento.
AES Estándar 128/192/256 bits.
ChaCha20 Moderno Stream cipher, rápido en CPU sin AES-NI, usado en TLS 1.3.
Blowfish/Twofish Legacy Reemplazados por AES.
RC4 Roto Sesgos en los primeros bytes; no usar.

Modos de operación (block ciphers)

AES procesa bloques de 16 bytes. Para datos más largos hay que combinar bloques con un modo:

Modo Cómo Problema
ECB Cada bloque cifrado independientemente bloques iguales → ciphertext igual (ECB penguin)
CBC Cada bloque XOR con el anterior antes de cifrar requiere IV; padding oracle attacks
CTR Convierte block cipher en stream cipher sin integridad → necesita MAC
GCM CTR + GHASH (autenticación) AEAD; el modo recomendado
OCB AEAD eficiente menos extendido, patentes históricas

Regla práctica: usa AES-256-GCM o ChaCha20-Poly1305. Cualquier otra cosa requiere justificación.

IV (Initialization Vector)

Un valor único por mensaje que evita que cifrar el mismo plaintext con la misma key produzca el mismo ciphertext. Reglas:

  • Para CBC: IV aleatorio, se transmite en claro junto al ciphertext.
  • Para CTR/GCM: IV/nonce único pero no necesariamente secreto. Reusar nonce con la misma key en GCM = catástrofe (recuperación de la key de autenticación).

Implementación de AES-256-CBC y AES-256-GCM con OpenSSL: codigo/0x730/aes_cbc.c, codigo/0x730/aes_gcm.c.


0x740 — Cifrado asimétrico

Cada parte tiene un par de keys: pública (se comparte) y privada (se guarda). Lo cifrado con la pública solo lo descifra la privada (y viceversa). Resuelve el problema de distribución de keys que tiene la simétrica.

Algoritmo Para qué Tamaño típico
RSA Cifrado, firma 2048 / 3072 / 4096 bits
DH (Diffie-Hellman) Acuerdo de key mismo orden que RSA
ECDH DH sobre curvas elípticas 256 / 384 bits → equivale a RSA 3072+
ECDSA / Ed25519 Firma 256 bits

Asimétrica es mucho más lenta que simétrica (factores 100x-1000x). Por eso nunca se usa para datos largos.

El esquema de RSA en 4 líneas

  1. Elegir dos primos grandes p, q.
  2. n = p · q. φ(n) = (p-1)(q-1).
  3. Elegir e coprimo con φ(n) (típicamente e = 65537).
  4. Calcular d = e^-1 mod φ(n). Pública = (n, e). Privada = (n, d).

Cifrar: c = m^e mod n. Descifrar: m = c^d mod n. La seguridad depende de que factorizar n sea difícil.

Bugs típicos de RSA en producción

  • e = 3 sin padding (textbook RSA): factible recuperar plaintext si m^3 < n.
  • Padding PKCS#1 v1.5 → padding oracle (Bleichenbacher). Solucionado con OAEP.
  • Primos predecibles porque el RNG falló (Heartbleed-era keys).
  • Misma n reutilizada entre dispositivos: GCD entre los n revela primos compartidos.

Para cualquier código nuevo: OAEP para cifrar, PSS para firmar, o mejor aún Ed25519/X25519.


0x750 — Cifrado híbrido

Lo que usa todo el mundo (TLS, Signal, PGP, age):

  1. Generar key simétrica aleatoria K.
  2. Cifrar el mensaje con K usando AES-GCM (rápido).
  3. Cifrar K con la pública RSA del destinatario (lento, pero K es solo 32 bytes).
  4. Enviar (K cifrada, mensaje cifrado).

El destinatario descifra K con su privada y luego descifra el mensaje con K.

TLS 1.3 hace esto con un giro: usa ECDHE (Diffie-Hellman efímero sobre curvas elípticas) para acordar la K, y los certificados RSA/ECDSA solo para firmar (no para cifrar K). Esto da forward secrecy: aunque alguien capture el tráfico hoy y robe la privada del servidor mañana, no puede descifrar las sesiones pasadas.


0x760 — Cracking de contraseñas

Las contraseñas no se almacenan en claro. Se almacenan como hash + salt, opcionalmente con factor de coste (PBKDF2, bcrypt, scrypt, Argon2).

Hashes que verás en /etc/shadow

$id$rounds=N$salt$hash
id Algoritmo Estado
1 MD5-crypt inseguro
5 SHA-256-crypt aceptable
6 SHA-512-crypt aceptable, default en muchas distros
2a/2b/2y bcrypt bueno
argon2id Argon2id el recomendado desde 2016

Tools

  • John the Ripper — formato auto-detectado, muy completo.
    john --wordlist=/usr/share/wordlists/rockyou.txt hashes.txt
    john --show hashes.txt
  • hashcat — GPU, mucho más rápido para hashes paralelizables.
    hashcat -m 1800 hashes.txt rockyou.txt    # SHA-512-crypt
    hashcat -m 3200 hashes.txt rockyou.txt    # bcrypt
  • Hash-Identifier / hashid / haiti — identificar formato.

Wordlists

  • rockyou.txt (/usr/share/wordlists/rockyou.txt.gz en Kali) — 14M passwords reales filtradas.
  • SecLists (https://github.com/danielmiessler/SecLists) — colecciones especializadas.
  • Generadas a medida con cewl (scrapea palabras de un sitio web), crunch, maskprocessor.

Ataques

Ataque Cómo
Diccionario hash(palabra) por cada palabra del wordlist
Diccionario + reglas aplica mutaciones (P@ssw0rd!, password123...)
Máscara brute force estructurado: ?l?l?l?l?d?d
Híbrido wordlist + máscara concatenados
Rainbow tables precomputado, ya no son útiles si hay salt

Demo

codigo/0x760/crack_demo.c — implementación didáctica de un cracker de SHA-256 sin sal contra un wordlist en memoria. No usar en producción, es ilustrativo.


0x770 — Cifrado Wi-Fi 802.11b

Esquema Año Estado
WEP 1997 Roto desde 2001. Recuperable en minutos.
WPA (TKIP) 2003 Roto parcialmente (Beck-Tews); evitable.
WPA2 (CCMP/AES) 2004 Roto el handshake (KRACK 2017), pero limitado.
WPA3 (SAE) 2018 Estado del arte; fallo Dragonblood 2019 (parcheado).

WEP es del libro. WPA2 con SAE/PSK fuerte sigue siendo lo mínimo aceptable hoy.

Captura del handshake WPA/WPA2

sudo airmon-ng start wlan0                                  # modo monitor
sudo airodump-ng -c 6 --bssid XX:XX:XX:XX:XX:XX -w cap wlan0mon
sudo aireplay-ng -0 5 -a XX:XX:XX:XX:XX:XX wlan0mon         # deauth para forzar reconnect
hashcat -m 22000 cap.hccapx rockyou.txt                     # crack offline

WPA2-PSK con password fuerte (>20 chars random) es brute-force-impracticable. PSK del operador típica (12 chars de la pegatina del router) → crackeable en horas con GPU.


0x780 — Ataques a WEP

WEP usa RC4 con una key de 40 o 104 bits + IV de 24 bits.

Por qué se rompió

  • IV reusado. Solo 2²⁴ ≈ 16M posibilidades. En una red activa se reciclan en horas, dando dos ciphertexts con la misma keystream → XOR de ambos elimina la keystream.
  • Sesgo de RC4 (FMS attack). Algunos IVs ("weak IVs") revelan info sobre la key.
  • PTW attack (2007): recupera key de 104 bits con ~40000 paquetes capturados. Minutos en una red con tráfico.

Reproducción de la suite aircrack-ng (red propia)

sudo airmon-ng start wlan0
sudo airodump-ng -c <ch> --bssid <bssid> -w wep wlan0mon    # captura
sudo aireplay-ng -3 -b <bssid> -h <mac_atac> wlan0mon        # ARP replay para generar tráfico
aircrack-ng -b <bssid> wep-01.cap                            # cracking

WEP no se ve casi nunca en 2025 — pero hay routers olvidados en pisos viejos y vending machines. Si lo encuentras es legacy puro y debe migrarse.

Lección general de cripto

  • No inventes algoritmos.
  • No inventes modos.
  • No inventes integraciones.
  • Usa libsodium o el wrapper de tu lenguaje (Go: crypto/, Python: cryptography, Rust: ring/rustcrypto). Toda implementación nueva en C es donde aparecen los bugs.

codigo/0x740/rsa_demo.c muestra RSA con OpenSSL EVP, codigo/0x730/aes_gcm.c muestra AES-256-GCM. Ambos usan APIs modernas de OpenSSL 3.


Siguiente: 0x800 — Conclusión.