RSA (Rivest-Shamir-Adleman, 1977) es el algoritmo de clave pública más utilizado en la historia de la criptografía. Basa su seguridad en la dificultad computacional de factorizar el producto de dos números primos grandes. Comprender por qué es seguro cuando se implementa correctamente es la clave para entender por qué se rompe cuando se implementa mal.
Cifrado: c = me mod N — Descifrado: m = cd mod N
RSA es seguro en teoría, pero en la práctica existen numerosas formas en que una implementación incorrecta lo hace completamente rompible. Las vulnerabilidades no son fallos en el algoritmo matemático, sino errores en cómo se generan o usan los parámetros.
| Debilidad | Causa | Ataque resultante | Dificultad de romperlo |
|---|---|---|---|
| N muy pequeño | Primos p, q pequeños (<512 bits) | Factorización directa | Trivial (<segundos) |
| p y q cercanos entre sí | p ≈ q, ambos cerca de √N | Factorización de Fermat | Muy fácil |
| d pequeño (e enorme) | e > N3/4 | Ataque de Wiener | Fácil |
| Primos compartidos | Mismo p en dos módulos distintos | GCD attack | Trivial |
| e pequeño (e=3) + sin padding | Mismo mensaje cifrado con 3 claves distintas | Ataque de Hastad (CRT) | Fácil |
| Mensajes relacionados + e=3 | Dos mensajes m, m+k cifrados con la misma clave | Franklin-Reiter | Moderado |
| Sin padding (textbook RSA) | Cifrado directo sin OAEP/PKCS | Múltiples ataques | Moderado |
RsaCtfTool es una herramienta Python de código abierto que implementa docenas de ataques matemáticos conocidos contra implementaciones débiles de RSA. Es la herramienta de referencia en competiciones CTF (Capture The Flag) para los retos de criptografía RSA. Acepta claves en múltiples formatos (PEM, n/e directamente, archivos de texto) y puede intentar todos los ataques automáticamente.
Si N tiene menos de ~512 bits (155 dígitos decimales), puede factorizarse en segundos con herramientas modernas. Con N menor de 200 bits, es trivial incluso en CPU. La web factordb.com mantiene una base de datos de millones de números ya factorizados.
Ver solución
El método de factorización de Fermat (1643) explota que si p y q son próximos, N puede expresarse como diferencia de cuadrados: N = a² - b² = (a+b)(a-b). El algoritmo busca el valor de a partiendo de √N hacia arriba hasta que a² - N sea un cuadrado perfecto.
Ver solución
El ataque de Wiener explota que, para acelerar el descifrado RSA, algunos implementadores eligen un exponente privado d pequeño (lo que implica que e será enormemente grande). Michael Wiener demostró en 1990 que si d < N1/4/3, entonces d puede recuperarse eficientemente usando aproximaciones de fracciones continuas de e/N.
Ver solución
Si dos módulos N1 y N2 comparten un factor primo p (es decir, N1 = p*q1 y N2 = p*q2), entonces el Máximo Común Divisor de N1 y N2 revela p instantáneamente. Este error ocurre cuando el generador de números aleatorios del sistema está sesgado o tiene poca entropía, produciendo el mismo primo en múltiples generaciones.
Un estudio de 2012 (Lenstra et al.) analizó millones de claves RSA públicas en internet y descubrió que el 0.2% de las claves de 1024 bits eran vulnerables a este ataque.
Ver solución
Ver solución
RsaCtfTool puede intentar automáticamente todos sus ataques implementados en orden de complejidad creciente. Es la forma más cómoda de atacar una clave RSA desconocida en un CTF: prueba primero los más rápidos y si ninguno funciona, pasa a los más costosos.
pipeline_fermat.py e instala las dependencias: pip3 install pycryptodome sympy. Luego: python3 pipeline_fermat.py. Verás todo el proceso: generación de la clave débil, cifrado, ataque de Fermat y recuperación del mensaje en menos de un segundo.| Ataque | Condición necesaria | Complejidad | Flag RsaCtfTool | Base matemática |
|---|---|---|---|---|
| Factorización directa | N < ~512 bits | Trivial | --attack factordb | Criba de Eratostenes, GNFS |
| Fermat | |p - q| muy pequeño | O(|p-q|) | --attack fermat | N = a² - b² |
| Wiener | d < N1/4/3 | O(log N) | --attack wiener | Fracciones continuas |
| Boneh-Durfee | d < N0.292 | Polinomial | --attack boneh_durfee | Reticulados (LLL) |
| GCD / Primos comunes | Dos N comparten un primo | O(log N) | --attack commonmodulus | Algoritmo de Euclides |
| Hastad (broadcast) | e pequeño + mismo m | Polinomial | --attack hastad | Teorema Chino del Resto |
| Franklin-Reiter | Mensajes relacionados + e pequeño | Polinomial | --attack franklin_reiter | MCD de polinomios |
| Blinding (Coppersmith) | Parte de m conocida | Polinomial | --attack coppersmith | Reticulados, LLL |
| e=1 | e = 1 (trivial) | Trivial | --attack e_is_1 | c = m^1 mod N = m |
| Small e + small m | m^e < N | Trivial | --attack smallfactors | Raiz e-ésima entera |
| Requisito | Valor correcto | Ataque que previene |
|---|---|---|
| Tamaño de N | ≥ 2048 bits (4096 para secretos a largo plazo) | Factorización directa |
| Generación de p y q | Completamente independientes, fuente criptográficamente aleatoria | Fermat, GCD attack |
| Diferencia |p-q| | Del orden de N/2 (automático si son aleatorios independientes) | Fermat |
| Exponente público e | 65537 (0x10001) estándar de la industria | Hastad, Wiener |
| Exponente privado d | Calculado como inverso de e (no elegido directamente) | Wiener, Boneh-Durfee |
| Padding | OAEP (RSA-OAEP) para cifrado, PSS para firma | Hastad, Franklin-Reiter, textbook attacks |
| Fuente de aleatoriedad | CSPRNG del sistema operativo (/dev/urandom, os.urandom()) | GCD attack (primos repetidos) |