Resumen
- RFC 3218 trató los errores, las respuestas y los tiempos del receptor como parte de la interfaz criptográfica. Si era posible distinguir un bloque RSAES-PKCS1-v1_5 inválido de otro válido que contenía una CEK equivocada, la distinción podía explotarse de forma adaptativa.
- El relleno aleatorio sustituía un desempaquetado inválido por una CEK nueva de la longitud esperada y dejaba avanzar el descifrado y la verificación. La clave falsa no era recuperación: servía para que el primer fallo se pareciera al fallo normal que produciría una clave incorrecta.
El secreto no tenía que aparecer en una pantalla. Bastaba con que la máquina revelara si el secreto, aún oculto, tenía la forma esperada.
Daniel Bleichenbacher mostró en 1998 que ese único bit era suficiente para construir un ataque de texto cifrado elegido adaptativo contra PKCS #1 v1.5. El atacante capturaba un cifrado RSA, lo transformaba, preguntaba indirectamente si el resultado descifrado respetaba el formato y elegía la siguiente transformación a partir de todas las respuestas anteriores. La clave privada nunca salía del receptor. Sus decisiones repetidas estrechaban el intervalo numérico en el que se encontraba el texto claro.
RFC 3218 trasladó la amenaza a Cryptographic Message Syntax. Se publicó en enero de 2002 como documento Informational. No definía una nueva identidad ni afirmaba que RSA estuviese roto en todos sus usos. Se ocupaba de una transición concreta: numerosos sistemas CMS ya transportaban con RSA PKCS #1 v1.5 la clave simétrica que cifraba el contenido, y la compatibilidad impedía reemplazar ese formato de una vez.
La codificación v1.5 comenzaba con 00 02, seguía con al menos ocho octetos aleatorios distintos de cero, incluía un separador 00 y terminaba con el valor transportado. Para CMS, ese valor era la content-encryption key, o CEK. La operación privada de RSA podía completarse y aun así entregar un bloque que no cumplía esa gramática.
De ahí surgían varias verdades, no una sola. La exponenciación RSA podía terminar. El bloque podía tener o no un formato válido. La CEK podía tener la longitud prevista para el algoritmo de contenido. Incluso con longitud correcta podía ser una clave falsa. El descifrado podía devolver bytes que después fallaran al comprobar el relleno, el MAC, la firma o el formato de la aplicación.
El software necesitaba distinguir esas etapas para operar. La red no debía convertirlas en una encuesta para el atacante.
La denominación Million Message Attack describía una escala operativa. A partir de un cifrado capturado C, el atacante enviaba valores relacionados, C' = C * S^e mod n. Aproximadamente una transformación de cada 2^16 podía producir un texto claro que empezara por 00 02. En el escenario analizado, RFC 3218 situó el trabajo total en torno a 2^20 mensajes y respuestas.
No era una cifra exacta para toda clave y todo servidor. Era una advertencia sobre la automatización. Un millón de consultas humanas serían costosas y visibles. Un agente de listas de correo, una pasarela u otro receptor desatendido podía procesarlas y responder sin que nadie examinara cada interacción. El servicio convertía volumen de red en paciencia criptográfica.
Una consulta podía desembocar en un bloque PKCS #1 mal formado, en un bloque válido con una CEK falsa, en un fallo de integridad, o en datos aleatorios que por casualidad parecieran tener un relleno CBC aceptable. Recuperar la CEK real con una transformación casual era extremadamente improbable.
El ataque no necesitaba nombrar todos esos resultados. Solo requería separar el bloque mal formado de la clase de fallos posteriores generados por una CEK equivocada pero bien codificada. Podía observar un texto de error, una respuesta frente a silencio, un cierre de conexión, un rebote de correo, una alerta de firma o una diferencia temporal reproducible.
RFC 3218 propuso como defensa principal el random filling. Si la descodificación PKCS #1 detectaba un formato incorrecto, el receptor generaba una CEK criptográficamente aleatoria con la longitud exigida por el cifrado de contenido. Después actuaba como si RSA hubiese entregado ese valor.
El contenido se descifraba con la clave inventada. Se ejecutaban las comprobaciones normales de relleno, integridad, firma y aplicación. La CEK aleatoria conduciría casi siempre a un rechazo posterior. El error visible y el tiempo del procesamiento debían parecerse a los de un bloque correctamente formado que transportaba simplemente la clave equivocada.
Por eso la CEK aleatoria no era una clave de recuperación. No reconstruía el secreto del remitente, no preservaba el contenido y no autorizaba el mensaje. Era material desechable creado para que el receptor pudiera continuar hacia un fracaso ordinario sin revelar el fracaso temprano.
Una CEK de reserva fija habría destruido la protección. La constante podría parecer conveniente para las pruebas y para ahorrar una llamada al generador aleatorio. Pero un adversario que la conociera podría cifrar contenido CMS con ella, adjuntar un transporte RSA deliberadamente inválido y observar el resultado. Si el receptor hubiese tomado la rama de reserva, el contenido pasaría sus controles; de lo contrario fallaría. La supuesta ocultación construiría un oráculo más limpio.
La clave sustitutiva debía ser nueva e impredecible en cada ocasión. Reutilizarla otorgaría a la rama de error una identidad estable que el contenido preparado podría reconocer.
También importaba el momento de generar el azar. Si el generador era lento y solo se invocaba tras detectar un error, la latencia delataba la ruta. RFC 3218 sugirió generar un candidato aleatorio para cada mensaje y descartarlo cuando el desempaquetado resultara válido. Ambos caminos asumían así un coste parecido.
Eso no constituía una demostración universal de tiempo constante. La memoria, el analizador, los registros, las colas de trabajo, la respuesta de correo o el procesamiento de la aplicación aún podían divergir. La recomendación impedía confundir un código de error uniforme con un comportamiento uniforme.
La longitud de la CEK abría otra frontera. Una biblioteca RSA genérica podía saber que el bloque era sintácticamente válido pero ignorar si el algoritmo de contenido requería 8, 16, 24 o 32 bytes. Si la capa CMS superior rechazaba una longitud incorrecta mediante una excepción distinta, el oráculo no desaparecía: ascendía por la pila.
La capa que conocía el algoritmo tenía que sustituir también los valores de longitud inválida. La propiedad de seguridad cruzaba los límites del software. La primitiva inferior no podía garantizarla cuando carecía del contexto necesario para clasificar todos los errores relevantes.
El RFC recomendó verificaciones más estrictas para encarecer la búsqueda: comprobar todos los octetos de relleno, la longitud de la CEK y, cuando correspondiera, los bits de paridad de los algoritmos DES. Cada condición reducía la probabilidad de que una transformación aleatoria fuera aceptada.
Sin embargo, un oráculo infrecuente seguía siendo un oráculo. Si la respuesta revelaba qué condición había fallado, el atacante podía continuar pagando el coste mayor.
El contenido CBC sin autenticación mostraba además por qué “se pudo descifrar” era una afirmación débil. Un texto aleatorio podía terminar con bytes que parecieran relleno. Si el programa miraba solo el último byte para decidir cuánto recortar, RFC 3218 estimaba una probabilidad aparente cercana a 1/32. Verificar todos los bytes requeridos la reducía aproximadamente a 1/255.
Ninguna de esas coincidencias hacía significativo el contenido. Un MAC o una firma daban un punto de rechazo mucho más sólido. Aun así, el receptor no podía publicar por separado el primer veredicto PKCS #1: la defensa consistía precisamente en fusionarlo con los fallos posteriores.
OAEP ofrecía una ruta criptográfica más limpia. PKCS #1 v2.0 había especificado RSAES-OAEP, y RFC 3218 indicó que el ataque descrito no le afectaba. Pero OAEP no era compatible en el cable con v1.5. Emisores, receptores, certificados, identificadores de algoritmo y programas instalados debían acordar el cambio.
La existencia de una primitiva mejor no apagaba el ecosistema antiguo. El relleno aleatorio protegía el periodo de coexistencia: limitaba lo que podía revelar el receptor legado mientras la migración avanzaba.
TLS había adoptado una regla semejante para los secretos pre-maestros cifrados con RSA. El servidor debía continuar con un valor aleatorio, en vez de revelar un error de formato o versión. La idea compartida no hacía idénticos los protocolos. Un intercambio TLS, un mensaje CMS y un agente de correo tenían respuestas, estados y efectos posteriores diferentes.
La lección residía por encima de RSA: un analizador interno no debe contestar una pregunta que el protocolo exterior no puede exponer con seguridad. El protocolo debe decidir cuánto trabajo continúa, qué rechazo final se muestra y qué señales laterales quedan disponibles.
RFC 3218 no garantizó autenticidad, tiempo constante, conformidad de implementaciones ni eliminación de toda vulnerabilidad RSA. Tampoco aportó un censo de despliegues. Su afirmación duradera era más precisa: si un adversario puede repetir una diferencia interna, la gestión de errores pasa a formar parte del criptosistema.
Informe para miembros
Contexto ampliado del perfil
Inicia sesión con el nivel de membresía adecuado para desbloquear el informe completo y las notas de las fuentes.
Solo para Strategic Circle
Strategic Circle
Abierto a todos los lectores. Desbloquea informes de perfil después de unirte e iniciar sesión.
Únete a Strategic CircleSolo para Leadership Alliance
Leadership Alliance
Para propietarios y directivos cualificados de activos de propiedad intelectual; inicia sesión para desbloquear los informes de la alianza.
Unirse a Leadership Alliance
