Lección 9 de 13
El cuerpo de 256 elementos: la aritmética de los bytes en AES
Cómo sumar, multiplicar y dividir bytes sin salirse de 8 bits: el cuerpo finito de 256 elementos que usa AES, con xtime, el inverso y un ejemplo resuelto.
Al terminar sabrás:
- Interpretar un byte como un polinomio de grado como máximo 7 con coeficientes 0 y 1
- Sumar bytes con XOR y multiplicarlos módulo x⁸+x⁴+x³+x+1 con xtime
- Explicar por qué todo byte no nulo tiene inverso
- Comprobar un inverso multiplicando
Si sabes qué es un número en binario y sumar módulo 2 (sin llevadas), puedes seguirlo. Lo demás (hexadecimal, XOR, permutaciones, polinomios módulo 2 y cuerpos finitos) se explica sobre la marcha.
Hasta la lección 8 hemos seguido a DES: una red de Feistel de 16 rondas cuya clave de 56 bits se quedó corta. Empezamos ahora la segunda mitad del relato, la de su sucesor, AES. Antes de ver cómo es AES por dentro, hay que aprender un idioma que DES no necesitaba: AES no trata los bytes como simples cadenas de 8 bits, sino como números que se pueden sumar, multiplicar y dividir. En esta lección aprendes esa aritmética. Es la de un cuerpo de 256 elementos, el mismo que usan los códigos Reed-Solomon de los códigos QR, que quizá conozcas del curso de códigos. Eso sí, los QR lo construyen con otro polinomio (), así que allí las tablas de multiplicar de los bytes son distintas.
La idea
Un byte tiene 256 valores posibles. Queremos sumar dos bytes y obtener otro byte, multiplicar dos bytes y obtener otro byte, y poder dividir entre cualquier byte distinto de cero, siempre sin salirnos de 8 bits.
Con los enteros usuales no sale. Si sumas te pasas de 255. Si haces la aritmética «del reloj» módulo 256, tampoco: , y un producto de dos números no nulos que da cero rompe la división (el no tendría inverso). Lo que necesitamos es un cuerpo con 256 elementos. Existe porque es potencia de un primo, y se construye igual que y en la lección sobre cuerpos finitos del curso de códigos: con polinomios y un polinomio irreducible.
Repaso Si no has hecho el curso de códigos
Un cuerpo es un conjunto donde puedes sumar, restar, multiplicar y dividir entre todo lo que no sea cero, con las reglas de siempre. Los racionales y los reales lo son. Existen cuerpos con un número finito de elementos, y su tamaño es siempre una potencia de un primo. El de 2 elementos son los bits , con . Los de elementos se construyen con polinomios de coeficientes y , tomando restos al dividir entre un polinomio irreducible (uno que no se puede escribir como producto de polinomios de menor grado), igual que toma restos al dividir entre un primo .
Un byte es un polinomio
Un byte se identifica con el polinomio
Hay polinomios de grado como máximo 7 con coeficientes y , uno por byte. Por ejemplo, en binario es , que es el polinomio . Y es , es decir, . Recuerda que escribimos los bytes en hexadecimal, así: , . A partir de aquí escribimos el hexadecimal en minúsculas, como hace FIPS 197: y son el mismo byte. El byte es el polinomio y el byte es el polinomio .
Sumar es hacer XOR
Los coeficientes se suman módulo 2. Sumar dos polinomios es sumar coeficiente a coeficiente, sin llevadas: eso es exactamente el XOR bit a bit. Así que
Compruébalo en binario: , que es . Como , cada byte es su propio opuesto, así que restar es lo mismo que sumar. Esa es la operación más barata de todas, y AES la usa continuamente (la lección siguiente la llama AddRoundKey).
Multiplicar: módulo un polinomio irreducible
Multiplicar dos polinomios de grado hasta 7 da uno de grado hasta 14, que ya no cabe en un byte. Se arregla tomando el resto al dividir entre un polinomio irreducible de grado 8. AES usa
es decir, en binario, o en hexadecimal. Que sea irreducible es lo que hace que sea un cuerpo (más abajo vemos por qué importa). El cuerpo resultante es
En la práctica la regla de reducción es una sola: en el cuerpo, , o sea
Cada vez que aparezca un , lo cambias por (esto es un XOR con ).
xtime: multiplicar por
Multiplicar por desplaza todos los coeficientes un lugar a la izquierda. Si el byte no tiene el bit 7 activo, el resultado cabe en 8 bits y ya está. Si tiene el bit 7 activo, aparece un , que se sustituye por . Esta operación se llama xtime:
- se desplaza el byte un bit a la izquierda (descartando el bit que sale);
- si el bit que salió era 1, se hace XOR con .
Multiplicar por es xtime. Y como cualquier byte es una suma de potencias de , toda multiplicación se reduce a xtime repetidos y XOR. Para multiplicar : escribe como suma de potencias de (sus bits), calcula con xtime y suma (XOR) los que correspondan.
El inverso
Como es irreducible, todo byte distinto de tiene un inverso: otro byte con el que el producto es . La razón de una línea: si un byte y un byte dieran producto cero, dividiría a , y un polinomio irreducible dividiendo a un producto divide a un factor, imposible porque y tienen grado menor que 8. Sin productos nulos entre no nulos, multiplicar por es una permutación de los 255 bytes no nulos, y alguno sale .
Si el polinomio no fuera irreducible, se rompería. Lo veremos en el ejercicio 3.
No hay una fórmula sencilla para calcular el inverso a mano. Se puede hacer con el algoritmo de Euclides para polinomios, o por tanteo, o con una tabla de 256 entradas. Aquí nos basta con comprobar un inverso dado, multiplicando. En la lección 11 verás que la operación SubBytes de AES calcula el inverso de cada byte (con , porque el cero no tiene inverso) y le aplica después una transformación sencilla.
Ejemplo resuelto
Producto . Primero, la lista de los xtime sucesivos de (es decir, ):
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
|---|---|---|---|---|---|---|---|---|
Veamos los pasos que tienen reducción. De a : el bit 7 era 0, solo desplazamos. De a : desplazamos y queda con un bit que salió (un 1), así que . De a : solo desplazar. De a : desplazamos y queda , salió un 1, y . Los tres siguientes (, , ) son solo desplazamientos.
Ahora , así que
Cuenta: y . Resultado:
Es el ejemplo que da el propio estándar FIPS 197. Con la misma tabla, da .
Un inverso. Afirmamos que . Lo comprobamos multiplicando. Primero los xtime de :
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | |
|---|---|---|---|---|---|---|---|
Y . Entonces
Agrupando, , y . Efectivamente, el producto es : es el inverso de , y se puede dividir por multiplicando por .
Ejercicios
Ejercicio 1
Calcula y escribe el resultado como polinomio. Después calcula , y .
Ver la solución
En binario, y . Su XOR es , que es el polinomio .
Para : tiene el bit 7 activo, así que desplazamos () y hacemos XOR con : .
Para : , así que . Por el procedimiento: desplazar da , y .
Para : , bit 7 activo; desplazado es , y .
Ejercicio 2
Calcula (nota que ). Después comprueba que , es decir, que es el inverso de .
Ver la solución
Como , tenemos . Para : el bit 7 es 0, así que es solo el desplazamiento, . Entonces .
Para el inverso: tiene el bit 7 activo. Desplazado es , y . Luego y .
Ejercicio 3
Si en lugar de se tomara el polinomio (que en hexadecimal es ), ¿seguiría siendo un cuerpo? Demuestra que no, calculando con ese módulo.
Ver la solución
Se tiene y . Entonces
porque al multiplicar, todos los términos intermedios se cancelan por pares (módulo 2). Con módulo eso vale . Dos bytes no nulos, y , con producto : es lo mismo que pasaba con módulo 256 al principio de la lección. Entonces no tiene inverso y no hay cuerpo. La causa es que en , que no es irreducible. Con el módulo bueno, , distinto de cero.
En resumen
- AES trata cada byte como un elemento del cuerpo : el byte es el polinomio , y es .
- Sumar es XOR, y restar es lo mismo.
- Multiplicar por es xtime: desplazar un bit y, si se sale un 1, hacer XOR con . Toda multiplicación se reduce a xtime y XOR; por ejemplo, .
- Como el polinomio es irreducible, todo byte no nulo tiene inverso; por ejemplo, .
Siguiente lección: AES visto desde arriba: bloques, rondas y estado
Para profundizar
- NIST, FIPS 197, Advanced Encryption Standard (AES), actualizado el 9 de mayo de 2023 (2023).
- J. Daemen y V. Rijmen, The Design of Rijndael, Springer (2002).
- C. Paar y J. Pelzl, Understanding Cryptography, Springer (2010).