Cifrado por bloques y HTTPS: historia, evolución y por qué GCM domina hoy

Cuando hablamos de cifrado por bloques, hablamos de un algoritmo de cifrado que opera cifrando bloques de tamaño fijo, en el caso de AES (Advanced Encryption Standard) bloques de 16, 24 o 32 bytes (128, 192 o 256 bits).

Ahora bien, este bloque básico (de 128 bits en su versión más sencilla) necesita un añadido extra para cifrar textos más largos de esos 16 bytes (como un email o una sesión HTTPS). Ahí es donde entran los modos de operación de cifrado, que son formas de aplicar AES repetidamente para cifrar datos más grandes que un solo bloque.

Algunos de estos modos de operación son más seguros que otros, y algunos de ellos como ECB o incluso CBC, se consideran inseguros. Si tu servidor web está configurado para utilizar TLS (Transport Layer Security, protocolo criptográfico para establecer comunicaciones seguras y cifradas) con ellos, cualquier análisis de seguridad va a pitar. Vamos a ver por qué.

Los principales modos de operación de cifrado por bloques son histórica y actualmente los siguientes:

ECB (Electronic Codebook): Realmente el más básico, y considerado a día de hoy inseguro. En este modo de funcionamiento, cada bloque es cifrado de forma independiente y además no hay ningún tipo de aleatoriedad, lo cual hace que se repitan bloques idénticos y lo hace totalmente inadecuado para datos estructurados o repetitivos, como imágenes o texto natural.

La ilustración de este problema se acabó convirtiendo en un icono de la comunidad criptográfica. ¿Qué pasa si tratamos de cifrar la mascota Tux de Linux con cifrado ECB? ¡Que si estamos cifrando pequeños bloques de una imagen podemos distinguir perfectamente la imagen, por muy cifrada que esté!

Imagen de Tux sin cifrar, con AES+ECB, y con un cifrado sin su problemática

CBC (Cipher Block Chaining): En este modo, cada bloque se cifra después de hacer XOR con el anterior, necesitando un vector de inicialización (IV) para arrancar con el primer bloque. Aunque no es tan terrible como el ECB, sí tiene problemas, en particular ataques de padding oracle y que si el IV no es aleatorio y único, pueden repetirse patrones. No debería utilizarse en HTTPS, y de hecho la versión 1.3 de TLS lo eliminó. No obstante, aún puede encontrarse en versiones anteriores como TLS 1.2, si no están bien configuradas.

El ataque de tipo padding oracle, aprovecha la problemática de que AES trabaja con bloques fijos de 16 bytes (128 bits). Estos bloques fijos, provocan que si el mensaje no es un múltiplo exacto de 16 bytes, hay que hacer padding; esto es, rellenar el hueco. Si queremos cifrar la palabra «hola» codificada en 4 bytes, tendremos que meter otros 12 de padding. Lo más habitual, es rellenarlo con un byte cuyo valor es el número de bytes agregados, lo que en nuestro caso significa que lo rellenaría con el byte 0x0C (12) en las doce ocasiones. El ataque se basa entonces en descubrir información basándose en la respuesta del sistema sobre si el padding es válido o no enviando textos cifrados modificados, pudiendo llegar a recuperar todo el texto plano original deduciendo byte a byte el contenido del mensaje sin cifrar.

Esto dio lugar en 2013 al ataque de temporización Lucky13 contra CBC en TLS 1.1 y 1.2, y al ataque POODLE en 2014 sobre SSL 3.0 con CBC. Tras varios intentos de introducir defensas como mensajes de error genéricos y variaciones en el padding, se acabó abandonando por completo y actualmente el uso de CBC se considera un agujero de seguridad.

Operativa de cifrado con CBC

CTR (Counter Mode): Este sistema de bloques utiliza un contador y un nonce (un vector de inicialización) para generar un flujo pseudoaleatorio. En cada bloque se incrementa el contador y se concatena con el nonce (nonce || contador o una variante similar), formando un valor único para cada bloque. Este bloque así generado se cifra entonces con AES y la clave de cifrado (K) para generar un bloque de keystream pseudoaleatorio, una clave diferente para cada bloque de datos. Después de esto, este bloque de keystream cifra mediante XOR el bloque de texto plano, y genera así el texto cifrado.

Obviamente, para poder descifrar el texto se tiene que conocer el nonce, así que a menudo se sitúa al principio del texto cifrado. No obstante, en ocasiones, buscando seguridad añadida, se envía por otro canal, o incluso es un número de secuencia conocido por ambos lados.

¡Pero ojo! Nunca debe ser un valor fijo acordado como secreto. El nonce no necesita ser secreto, pero sí debe ser único por clave, y el verdadero peligro está en reutilizarlo. El nonce no debe repetirse, porque si lo hace es cuando el atacante puede extraer algo útil. Si se reutiliza el mismo nonce con la misma clave, se está reutilizando el mismo keystream. Y eso va a hacer que si uno de los mensajes es parcialmente conocido o predecible, el otro pueda ser reconstruído.

Un patrón similar fue el que afectó a WEP, el desastroso sistema de cifrado original de las redes Wi-Fi que a tanta gente proporcionó Internet gratuito. Aunque WEP utilizaba otro cifrador de flujo (RC4) tenía el mismo talón de Aquiles: reutilizaba los vectores de inicialización (IVs, equivalentes a nuestro nonce aquí) y permitía romperlo por completo.

Operativa de cifrado con CTR

GCM (Galois/Counter Mode): Esta es actualmente la estrella en HTTPS, VPNs y comunicaciones seguras modernas. Es una evolución del modo CTR que añade autenticación integrada.

La primera fase de cifrado va a ser la misma que en CTR. Se utiliza un nonce (único por mensaje) y un contador por bloque, generando el keystream cifrando nonce || contador con AES y una clave secreta (K). El texto cifrado se obtiene aplicando XOR entre este keystream y el texto plano.

La segunda fase, que no existía en CTR, es la de autenticación (GMAC). Se va a añadir un código de autenticación (MAC) llamado etiqueta GCM, que va a garantizar la integridad (el mensaje no fue alterado) y la autenticidad (el mensaje viene del remitente correcto). Para generar esta etiqueta GCM, va a tomar el texto cifrado, el nonce y datos adicionales opcionales (AAD, Additional Authenticated Data), y a realizar operaciones matemáticos en el campo de Galois (operando con los datos como polinomios) utilizando una subclave derivada de K. La etiqueta resultante, habitualmente de 128 bits, se envía junto al mensaje.

El receptor verificará la etiqueta antes de descifrar, descartando el mensaje si no coincide. El AAD se utiliza para autenticar metadatos sin cifrarlos, como puede suceder con las cabeceras del protocolo de transmisión de datos, lo que evita replay attacks cuando se incluyen cabeceras como el número de secuencia.

AES-GCM es el modo de cifrado dominante hoy en HTTPS, especialmente en servidores y entornos con soporte para aceleración por hardware, pero obviamente no es el fin de la historia. Actualmente merece la pena mencionar ChaCha20-Poly1305. Consta de un cifrador simétrico de flujo (ChaCha20), una alternativa al AES rápida, segura y eficiente en software, y un algoritmo de autenticación de mensajes (Poly1305) para verificar la integridad y autenticidad del mensaje cifrado. Su uso se ha extendido particularmente porque el ChaCha20 es más rápido en CPU cuando no hay un hardware específico de cifrado, lo que ha propiciado su adopción en dispositivos móviles.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio