La lección anterior terminó con una cuenta incómoda: RSA da 128 bits de seguridad con claves de 3072 bits, pero para llegar a los 256 bits del estándar de oro harían falta claves de ~15360 bits — un crecimiento tan malo que en la práctica nadie lo hace. Esta lección presenta la familia de trampillas que resolvió ese problema y que hoy domina la criptografía asimétrica, desde tu móvil hasta TLS: la criptografía de curva elíptica (ECC, Elliptic Curve Cryptography). Verás por qué consigue las mismas garantías con claves de solo 256 bits, la intuición geométrica de su función de un solo sentido (sin álgebra pesada, prometido), qué curvas concretas importan hoy y cuáles evitar, y cómo generar y serializar claves EC con pyca/cryptography. Al final, MediNube tomará una decisión de arquitectura que condicionará el resto del módulo: qué curva usar para las futuras firmas de recetas electrónicas.
Contenido
- El problema de RSA: claves que crecen fatal
- Qué es una curva elíptica: la suma de puntos
- La trampilla: el logaritmo discreto elíptico
- Las curvas que importan: NIST y Bernstein
- Generación de claves EC con pyca/cryptography
- Serialización PEM: igual que en RSA, pero en miniatura
- RSA o ECC: criterio de elección práctico
- La decisión de MediNube
El problema de RSA: claves que crecen fatal
La seguridad de RSA descansa en la factorización, y la factorización tiene un problema para el defensor: los algoritmos conocidos para atacarla (como la criba general del cuerpo de números, GNFS) son subexponenciales — mucho mejores que la fuerza bruta. Consecuencia: para ganar unos pocos bits de seguridad hay que agrandar la clave RSA muchísimo.
Con las curvas elípticas pasa lo contrario: el mejor ataque conocido contra su trampilla es esencialmente genérico (coste ~2^(n/2), el mismo orden que la paradoja del cumpleaños que viste en 03-01). Eso significa que una clave EC de n bits da ~n/2 bits de seguridad, y la tabla de equivalencias queda así:
| Bits de seguridad | Clave RSA necesaria | Clave ECC necesaria | Equivalente simétrico |
|---|---|---|---|
| 80 (obsoleto) | 1024 bits | 160 bits | — (roto/prohibido) |
| 112 (mínimo hoy) | 2048 bits | 224 bits | 3DES (a extinguir) |
| 128 (estándar del curso) | 3072 bits | 256 bits | AES-128 |
| 192 | 7680 bits | 384 bits | AES-192 |
| 256 | ~15360 bits | 512 bits | AES-256 |
Lee la tabla por filas: para el estándar de 128 bits (regla de oro 5), RSA necesita una clave 12 veces más grande que ECC. Y la diferencia se dispara hacia abajo: en la fila de 256 bits, RSA es directamente inviable en la práctica y ECC sigue siendo una clave de 64 bytes.
¿Por qué importa, más allá de la elegancia?
- Rendimiento. Las operaciones EC sobre números de 256 bits son mucho más rápidas que las exponenciaciones RSA sobre números de 3072. En un servidor que hace miles de conexiones TLS por segundo, la diferencia se nota en la factura.
- Ancho de banda. Cada clave pública, cada firma, cada intercambio viaja por la red. 32-64 bytes frente a 384 en cada handshake, multiplicado por millones de conexiones.
- Móvil e IoT. Un sensor médico con batería y un microcontrolador modesto puede hacer ECC con soltura; RSA-3072 le cuesta caro. Para MediNube, que planea integrar dispositivos de monitorización domiciliaria, esto no es teórico.
- Generación de claves. Generar un par RSA-3072 implica buscar primos enormes (segundos); generar un par EC es elegir un número aleatorio (microsegundos). Esto habilitará las claves efímeras de 04-04.
Qué es una curva elíptica: la suma de puntos
Una curva elíptica es el conjunto de puntos (x, y) que cumplen una ecuación del tipo:
Dibujada sobre los números reales, es una curva suave y simétrica respecto al eje X. Lo interesante no es la curva en sí, sino que sobre sus puntos se puede definir una operación de suma con una regla geométrica sorprendentemente simple:
Para sumar dos puntos P y Q: traza la recta que los une. Esa recta corta la curva en un tercer punto. Refleja ese punto respecto al eje X: el resultado es
P + Q.
flowchart TD
A["Puntos P y Q sobre la curva"] --> B["Trazar la recta que pasa por P y Q"]
B --> C["La recta corta la curva en un tercer punto R'"]
C --> D["Reflejar R' respecto al eje X"]
D --> E["Resultado: P + Q = R"]
F["Caso especial: sumar P consigo mismo (P + P = 2P)"] --> G["Se usa la recta TANGENTE a la curva en P"]
G --> C
Con esa suma definida, se define la multiplicación por un escalar como suma repetida:
donde G es un punto fijo de la curva llamado punto generador (viene definido en el estándar de cada curva, es público). Y aquí está el truco que lo hace practicable: no hace falta hacer k sumas de verdad. Igual que pow(m, e, n) no multiplica e veces, la multiplicación escalar se calcula con el método de duplicar-y-sumar: 8·G = 2·(2·(2·G)) — unas ~256 duplicaciones y sumas bastan aunque k tenga 256 bits. La dirección "fácil" es realmente fácil.
Dos matizaciones honestas, para que la intuición no te engañe:
- En criptografía la curva no vive sobre los números reales sino sobre un cuerpo finito (coordenadas enteras módulo un primo grande). El dibujo continuo desaparece y queda una nube de puntos, pero las fórmulas de la suma geométrica siguen funcionando exactamente igual. La intuición de la recta y el reflejo es válida; el dibujo, no.
- La ecuación exacta y sus parámetros
a,b, el primo del cuerpo y el generadorGson lo que define una curva concreta (P-256, Curve25519...). Elegir mal esos parámetros puede destruir la seguridad — por eso solo se usan curvas estandarizadas y auditadas, nunca curvas propias (regla de oro 1, otra vez).
La trampilla: el logaritmo discreto elíptico
Ya tienes las dos piezas para ver la función de un solo sentido:
- Fácil: dado un escalar secreto
ky el generadorG, calcular el puntoQ = k·G(duplicar-y-sumar, microsegundos). - Inviable: dado el punto
Qy el generadorG, recuperar el escalark. Este es el problema del logaritmo discreto elíptico (ECDLP), y no se conoce ningún atajo en curvas bien elegidas: el mejor ataque cuesta del orden de 2^128 operaciones para una curva de 256 bits.
La correspondencia con lo que ya sabes de 04-01 es directa:
| RSA | ECC | |
|---|---|---|
| Clave privada | Los primos p, q (y d) |
El escalar k (un número de 256 bits) |
| Clave pública | El módulo n = p·q (y e) |
El punto Q = k·G |
| Dirección fácil | Multiplicar primos | Multiplicar escalar por punto |
| Problema inviable | Factorizar n |
ECDLP: recuperar k desde Q |
| Mejor ataque conocido | Subexponencial (GNFS) → claves enormes | Genérico ~2^(n/2) → claves compactas |
Fíjate en que generar un par de claves EC es trivial: la privada es literalmente un número aleatorio de 256 bits salido del CSPRNG (regla de oro 3), y la pública se obtiene con una multiplicación escalar. Nada de buscar primos. Por eso generar claves EC es miles de veces más rápido que generar claves RSA — un detalle que parecerá menor hasta que en 04-04 queramos generar un par nuevo por cada conexión.
Nota para el futuro (y para que no te asuste un titular): tanto la factorización como el logaritmo discreto — clásico y elíptico — caerían ante un ordenador cuántico a gran escala con el algoritmo de Shor. Hoy no existe tal máquina, y la respuesta (criptografía post-cuántica) es la lección 06-05. Para todo lo que construimos en este módulo, ECC es el estándar actual y correcto.
Las curvas que importan: NIST y Bernstein
En la práctica no eliges parámetros: eliges una curva con nombre de un catálogo muy corto. Las que necesitas conocer se agrupan en dos familias:
Las curvas NIST: P-256 y P-384
Estandarizadas por el NIST estadounidense (P-256 también se llama secp256r1 o prime256v1 — tres nombres, la misma curva; P-384 es secp384r1). Son el estándar de la interoperabilidad: certificados TLS, tarjetas inteligentes, DNIe, APIs gubernamentales, hardware HSM... si un sistema ajeno te exige una curva concreta, casi seguro será una de estas. Son seguras con una implementación correcta, pero tienen dos sombras:
- Implementarlas en tiempo constante es difícil, y ha habido implementaciones históricas con fugas por canal lateral (recuerda los timing attacks de 01-04). La de
pyca/cryptography(OpenSSL por debajo) es correcta; el riesgo está en implementaciones caseras o exóticas. - Sus constantes derivan de semillas no explicadas públicamente, lo que ha generado desconfianza histórica (nunca se ha demostrado nada malo, pero la criptografía moderna prefiere constantes justificables).
Las curvas de Bernstein: Curve25519 y Ed25519
Diseñadas por Daniel J. Bernstein con la filosofía opuesta: que la implementación segura sea el camino fácil. Constantes explicadas y minimalistas, operaciones en tiempo constante por diseño de la propia curva, sin casos especiales que un programador pueda gestionar mal, sin decisiones peligrosas delegadas en quien la usa. Vienen en dos presentaciones que conviene no confundir:
- X25519 (sobre Curve25519): la curva para intercambio de claves. Es la protagonista de 04-04.
- Ed25519: la curva (una transformación de la misma) para firmas digitales. Es la protagonista de 04-03.
Son las curvas preferidas del software moderno: SSH, Signal, WireGuard, age, y una fracción creciente de TLS las usan por defecto.
| P-256 / P-384 (NIST) | Curve25519 / Ed25519 (Bernstein) | |
|---|---|---|
| Seguridad | ~128 / ~192 bits | ~128 bits |
| Punto fuerte | Interoperabilidad universal, requisitos normativos | Diseño a prueba de errores, constant-time por construcción, rapidez |
| Punto débil | Implementaciones históricas con canales laterales; constantes opacas | Algún sistema heredado o normativa aún no las acepta |
| Cuándo elegirla | Te la impone un tercero (certificados, hardware, compliance) | Siempre que la decisión sea tuya |
Y las que debes saber evitar: cualquier curva por debajo de 224 bits (SECP192R1, SECT163K1... si las ves en código heredado, es un hallazgo), y curvas exóticas elegidas sin motivo. SECP256K1 es un caso aparte: es la curva de Bitcoin/Ethereum, correcta en su nicho, pero fuera de él no hay razón para elegirla.
Generación de claves EC con pyca/cryptography
Las tres variantes que usarás, cada una con su módulo en hazmat.primitives.asymmetric:
from cryptography.hazmat.primitives.asymmetric import ec, ed25519, x25519 # 1) Curva NIST P-256: cuando la interoperabilidad manda. priv_nist = ec.generate_private_key(ec.SECP256R1()) pub_nist = priv_nist.public_key() print(priv_nist.curve.name) # secp256r1 print(priv_nist.curve.key_size) # 256 # 2) Ed25519: la curva de FIRMA moderna (la desarrollamos en 04-03). priv_firma = ed25519.Ed25519PrivateKey.generate() pub_firma = priv_firma.public_key() # 3) X25519: la curva de INTERCAMBIO DE CLAVES (la desarrollamos en 04-04). priv_intercambio = x25519.X25519PrivateKey.generate() pub_intercambio = priv_intercambio.public_key()
Detalles que conviene interiorizar:
- Con las curvas NIST, la curva se pasa como parámetro (
ec.generate_private_key(ec.SECP256R1())) y el mismo objeto sirve para varios usos. Con las curvas de Bernstein, la clase es la curva y el uso:Ed25519PrivateKeysolo sabe firmar,X25519PrivateKeysolo sabe intercambiar. Esa rigidez es una ventaja: la API te impide reutilizar una clave para dos propósitos distintos, un error clásico. - No hay
key_sizeque elegir nipublic_exponentque recordar: la curva ya define todo. Menos decisiones, menos formas de equivocarse — exactamente la filosofía Bernstein. - La generación es instantánea. Genera mil pares en un bucle y cronometra; haz lo mismo con
rsa.generate_private_keyy compara (spoiler: no querrás esperar). - Fiel a lo aprendido: la privada es un escalar aleatorio del CSPRNG del sistema; la pública, un punto.
pyca/cryptographyno te deja ver el escalar por accidente, y así debe ser.
Lo que no vamos a hacer todavía: ni priv_firma.sign(...) ni priv_intercambio.exchange(...). Cada operación tiene su lección (04-03 y 04-04) y su contexto; hoy el objetivo es tener las claves y entender por qué son tan pequeñas.
Serialización PEM: igual que en RSA, pero en miniatura
Todo lo aprendido en 04-01 sobre PEM aplica sin cambios — misma API, mismos formatos, misma disciplina de cifrar la privada:
from cryptography.hazmat.primitives import serialization
# Privada Ed25519: PKCS8 + cifrada con passphrase, como siempre.
pem_priv = priv_firma.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.BestAvailableEncryption(
b"frase-de-medinube"
),
)
# Pública: SubjectPublicKeyInfo, sin cifrar.
pem_pub = pub_firma.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo,
)
print(pem_pub.decode())
# -----BEGIN PUBLIC KEY-----
# MCowBQYDK2VwAyEA... ← ¡el PEM entero cabe en dos líneas!
# -----END PUBLIC KEY-----
# Cargar de vuelta: las mismas funciones de 04-01.
priv2 = serialization.load_pem_private_key(pem_priv, password=b"frase-de-medinube")
pub2 = serialization.load_pem_public_key(pem_pub)Compara ese PEM público de ~4 líneas con el de RSA-3072 (una decena de líneas de Base64): es la tabla de equivalencias hecha visible. Nota práctica: load_pem_public_key devuelve el tipo correcto según el contenido (Ed25519PublicKey, EllipticCurvePublicKey, RSAPublicKey...) — si tu código espera una curva concreta, comprueba el tipo con isinstance al cargar, no lo des por hecho.
RSA o ECC: criterio de elección práctico
La pregunta que te harás en cada proyecto nuevo, respondida en una tabla:
| Criterio | RSA (3072+) | ECC (Ed25519/X25519, o P-256) |
|---|---|---|
| Seguridad a igual configuración | Equivalente | Equivalente |
| Tamaño de claves y firmas | Cientos de bytes | Decenas de bytes |
| Velocidad (firma, intercambio, generación) | Lenta, y generar claves, muy lenta | Rápida en todo |
| Compatibilidad con sistemas antiguos | Universal, décadas de despliegue | Excelente en software moderno; algún heredado no la habla |
| Riesgo de implementación | Padding correcto es crítico (OAEP/PSS) | Mínimo con 25519; medio con NIST fuera de librerías serias |
| Cifrar pequeños mensajes directamente | Sí (OAEP, ≤318 bytes) | No directamente (se usa vía intercambio + simétrica, 04-04/04-05) |
| Veredicto para código nuevo | Solo si un tercero lo exige | Elección por defecto |
La última fila de la izquierda merece un apunte: ECC no tiene un equivalente directo del "cifra este mensajito con la pública" de RSA-OAEP. Con curvas elípticas, la confidencialidad se construye combinando intercambio de claves y cifrado simétrico — que es justo el camino de 04-04 y 04-05, y es también como funciona el mundo real. No es una carencia; es que el patrón de RSA-OAEP era el atajo, no la norma.
La decisión de MediNube
Toca aplicar el criterio. En la reunión de arquitectura de la capa de seguridad hay dos frentes abiertos:
- Firmas de recetas electrónicas (la deuda del módulo 1): cada médico firmará las recetas que emita, y farmacias externas deberán poder verificarlas. Ningún sistema heredado impone RSA aquí — el sistema es nuevo. Decisión: Ed25519. Claves de 32 bytes que caben en cualquier sitio, firmas rápidas y compactas, y una API que no permite equivocarse. Cada médico de la Clínica Sol y del Centro Médico Luna tendrá su par Ed25519. Los detalles, en la próxima lección.
- Canal seguro entre MediNube y las clínicas (la deuda de 02-01): X25519 para el intercambio de claves, por las mismas razones. Se materializa en 04-04.
¿Y el par RSA-3072 que generamos en 04-01? Se queda: la integración con el sistema de un hospital público exige RSA por normativa, y ahí RSA-OAEP sigue siendo correcto. Convivirán — la criptoagilidad (regla de oro 8) consiste exactamente en poder mantener ambas familias y jubilar una sin reescribir el sistema.
Y la pregunta incómoda de 04-01 sigue intacta, ahora multiplicada: si cada médico tiene una clave pública Ed25519, ¿cómo sabe una farmacia de qué médico es cada clave? Anótala; en 04-04 volverá con dramatismo.
Errores Comunes y Consejos
- Comparar tamaños de clave entre familias. "Mi RSA de 3072 es más seguro que tu Ed25519 de 256" es falso: ambos dan ~128 bits de seguridad. Los bits de clave solo son comparables dentro de la misma familia; lo que se compara entre familias son los bits de seguridad.
- Elegir la curva "más grande por si acaso". P-521 o firmas RSA-4096 rara vez aportan nada frente a 25519/P-256 y encarecen todo. 128 bits de seguridad es el estándar del curso; súbelo solo con un requisito concreto (normativa, longevidad extrema de los datos).
- Confundir Ed25519 con X25519. Parientes, pero no intercambiables: una es de firma y la otra de intercambio, con formatos de clave distintos. La API de
pyca/cryptographyte protege (clases separadas); otros ecosistemas no siempre. - Reutilizar la misma clave para firmar e intercambiar. Aunque una librería lo permitiera, es un antipatrón clásico: cada propósito, su par de claves. Guarda esta regla para cuando en 06-01 hablemos de inventario y rotación de claves.
- Implementar la aritmética de curvas a mano. Las fórmulas de la suma de puntos caben en pantalla y la tentación es real. Pero los casos especiales (punto en el infinito,
P + (-P), tiempo constante) son un campo de minas. Regla de oro 1: la curva se elige, no se implementa. - Curvas pequeñas u oscuras en código heredado.
SECP192R1o similares por debajo de 224 bits: hallazgo de seguridad, a migrar. Y si vesSECP256K1fuera de un contexto blockchain, pregunta por qué — casi seguro fue un copy-paste. - Guardar la privada EC sin cifrar porque "es pequeñita". El tamaño no cambia la disciplina de 04-01: PKCS8 +
BestAvailableEncryption, passphrase fuera del repositorio.
Ejercicios
-
La tabla, interiorizada. Sin mirar la tabla: (a) ¿qué tamaño de clave ECC necesitas para 192 bits de seguridad y qué tamaño tendría el RSA equivalente? (b) ¿Por qué la relación no es lineal — por qué RSA "crece fatal" y ECC crece suave? (c) ¿Cuántos bits de seguridad da una clave EC de 256 bits y por qué no 256?
-
Duelo de generación. Escribe un script que genere 50 pares Ed25519 y 3 pares RSA-3072, cronometrando cada tanda con
time.perf_counter(). Calcula el coste medio por par y el factor de diferencia. Serializa una pública de cada familia a PEM y compara longitudes conlen(). ¿Qué implicación tiene el resultado para un servidor que quisiera generar un par efímero por conexión (anticipo de 04-04)? -
Código heredado. Auditas este arranque en MediNube:
from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives import serialization def generar_par_medico_MAL(): priv = ec.generate_private_key(ec.SECP192R1()) pem = priv.private_bytes( serialization.Encoding.PEM, serialization.PrivateFormat.PKCS8, serialization.NoEncryption(), ) return pemIdentifica los dos problemas, escribe
generar_par_medicocorregida (recuerda la decisión de MediNube: estas claves firmarán recetas) y justifica cada cambio.
Soluciones
-
(a) ECC de 384 bits (P-384); el RSA equivalente serían 7680 bits, que prácticamente nadie despliega. (b) Porque los mejores ataques son de naturaleza distinta: contra RSA existe un algoritmo subexponencial (GNFS), así que cada bit extra de seguridad exige inflar mucho la clave; contra el ECDLP en curvas bien elegidas solo hay ataques genéricos de coste ~2^(n/2), así que basta añadir 2 bits de clave por cada bit de seguridad. (c) ~128 bits, precisamente por ese 2^(n/2): el mismo fenómeno "mitad del tamaño" que la paradoja del cumpleaños imponía a los hashes en 03-01.
import time
from cryptography.hazmat.primitives.asymmetric import ed25519, rsa
from cryptography.hazmat.primitives import serialization
t0 = time.perf_counter()
for _ in range(50):
ed25519.Ed25519PrivateKey.generate()
t_ed = (time.perf_counter() - t0) / 50
t0 = time.perf_counter()
for _ in range(3):
rsa.generate_private_key(public_exponent=65537, key_size=3072)
t_rsa = (time.perf_counter() - t0) / 3
print(f"Ed25519: {t_ed*1000:.3f} ms/par | RSA-3072: {t_rsa*1000:.1f} ms/par "
f"| factor: x{t_rsa/t_ed:,.0f}")
spki = serialization.PublicFormat.SubjectPublicKeyInfo
pem_ed = ed25519.Ed25519PrivateKey.generate().public_key().public_bytes(
serialization.Encoding.PEM, spki)
pem_rsa = rsa.generate_private_key(public_exponent=65537, key_size=3072) \
.public_key().public_bytes(serialization.Encoding.PEM, spki)
print(len(pem_ed), len(pem_rsa)) # ~113 frente a ~625 bytesEl factor típico ronda entre miles y decenas de miles: Ed25519 tarda microsegundos (elegir 32 bytes aleatorios y una multiplicación escalar); RSA-3072 tarda de decenas a cientos de milisegundos (buscar dos primos enormes, y además con duración variable — a veces los primos aparecen rápido, a veces no). Implicación: generar un par EC por conexión es gratis, generar un par RSA por conexión sería un suicidio de rendimiento. Esa asimetría es la que hace viables las claves efímeras y la forward secrecy de 04-04.
- Los dos problemas: (1)
SECP192R1es una curva de ~96 bits de seguridad, muy por debajo del mínimo — insuficiente y prohibida para código nuevo; (2)NoEncryption()guarda la privada del médico desnuda: quien lea el fichero puede firmar recetas como ese médico. Corrección:
from cryptography.hazmat.primitives.asymmetric import ed25519
from cryptography.hazmat.primitives import serialization
def generar_par_medico(passphrase: bytes):
"""Par de claves de firma de un médico (decisión MediNube: Ed25519)."""
priv = ed25519.Ed25519PrivateKey.generate()
pem_priv = priv.private_bytes(
serialization.Encoding.PEM,
serialization.PrivateFormat.PKCS8,
serialization.BestAvailableEncryption(passphrase),
)
pem_pub = priv.public_key().public_bytes(
serialization.Encoding.PEM,
serialization.PublicFormat.SubjectPublicKeyInfo,
)
return pem_priv, pem_pubJustificación: Ed25519 en lugar de otra curva NIST porque el sistema de recetas es nuevo (nada impone interoperabilidad NIST) y es la decisión de arquitectura tomada en esta lección; la passphrase entra como parámetro porque debe venir de fuera del código (gestor de secretos — módulo 6), jamás escrita en el fuente.
Conclusión
Ya tienes la segunda gran trampilla de la criptografía asimétrica. Sobre una curva elíptica se define una suma de puntos geométrica, y con ella la multiplicación escalar Q = k·G: calcular Q desde k es instantáneo, recuperar k desde Q — el logaritmo discreto elíptico — es inviable. Como los mejores ataques contra el ECDLP son genéricos (~2^(n/2)) y contra RSA son subexponenciales, ECC da los mismos 128 bits de seguridad con claves de 256 bits en vez de 3072: menos bytes en la red, operaciones más rápidas y generación de claves prácticamente gratis. Conoces el catálogo (P-256/P-384 cuando la interoperabilidad manda; Ed25519 para firmar y X25519 para intercambiar cuando eliges tú, que es casi siempre), sabes generar y serializar las tres variantes con pyca/cryptography, y MediNube ha tomado su decisión: Ed25519 para las firmas de los médicos, X25519 para el canal con las clínicas. Pero fíjate en lo que tienes entre manos: claves capaces de firmar... y todavía no sabes firmar. Es hora de saldar la deuda más antigua del curso — el no repudio prometido en el módulo 1 — y de que la Dra. de la Clínica Sol firme su primera receta electrónica. Eso es la próxima lección, 04-03: Firmas Digitales. Nos vemos allí.
Curso de Criptografía Aplicada
Módulo 1: Fundamentos de la Criptografía
- Qué es la criptografía y para qué sirve
- Codificación, ofuscación y cifrado
- Aleatoriedad y entropía
- El principio de Kerckhoffs y las reglas de oro
Módulo 2: Criptografía Simétrica
- Cifrado simétrico: AES y ChaCha20
- Modos de operación
- Cifrado autenticado (AEAD)
- Derivación de claves (KDF)
Módulo 3: Hashes, MAC y Contraseñas
- Funciones hash criptográficas
- Autenticación de mensajes con HMAC
- Almacenamiento seguro de contraseñas
Módulo 4: Criptografía Asimétrica
- Fundamentos de clave pública y RSA
- Criptografía de curva elíptica
- Firmas digitales
- Intercambio de claves: Diffie-Hellman
- Cifrado híbrido
Módulo 5: PKI, Certificados y TLS
- Certificados X.509 y autoridades de certificación
- TLS en la práctica
- Gestión del ciclo de vida de certificados
