You are on page 1of 17

UNIVERSIDAD COMPLUTENSE DE MADRID

MÁSTER EN INVESTIGACIÓN EN INFORMÁTICA

SEGURIDAD EN COMPUTADORES

AUTOR: Juan García-Prieto Cuesta


15 de septiembre de 2010

AES

Objetivo
Generalmente, los procesos de encriptación no son conocidos por los usuarios de los mismos.
Y, más aun, la algorítmica suele asociarse más bien a un “oscuro proceso” que no permite
análisis por ingeniería inversa. Las matemáticas no trivilaes (por ejemplo los Cuerpos Finitos)
generalmente hacen demasiado complicado entender qué hace exactamente el algoritmo de
encriptación.

El propósito del presente documento es precisamente describir de una manera sencilla, y


no completa pero suficientemente correcta el proceso matemático que subyace detrás del
proceso. Escogiendo para ello, uno de los algoritmos más conocidos, y más extensamente
utilizados: el AES-128.

Se desarrollará un proceso de cifrado describiendo lo más claramente posible, las operaciones


que tienen lugar en cada fase. Por este motivo, este documento no debe entenderse como una
descripción completa o un manual sobre el estándar, sino más bien una guía de acercamiento y
más aun, es muy recomendable acudir al estándar (ver apéndice) y a la biliografía relacionada
con Cuerpos de Galois.
Presentación
Advanced Encription Standard método de cifrado simétrico que se adopta el 26 de mayo
de 2006 como estándar en comunicaciones cifradas de EEUU. Es uno de los algoritmos
más populares de criptografía simétrica, y tras ser aprovado por FIPS (Federal Information
Processing Standars and Publications) su uso es obligado para los departamentos federales y
agencias gubernamentales de EEUU, cuando la información requiera protección criptográfica.

Basado en algoritmo de Rijndael, consiste en un método de cifrado por bloques de 128bits


mediante claves de cifrado de 128, 192 y 256 bits. Dependiendo de la longitud de clave
utilizada, se refiere al algoritmo como AES-128, AES-192, AES-256.

El estándar comenzó su aplicación efectiva el 26 de mayo de 2002, y con una descripción


inusualmente sencilla, su uso se ha expandido desde entonces. Una de las claves del éxito
reside en que puede implementarse con relativa eficacia mediante SW y firmware, aun cuando
es en la implementación HW donde la encriptación puede realizarse muy eficientemente. No se
conocen, sin embargo, ataques fructíferos contra el mismo y las estimaciones respecto al coste
de operaciones para una rotura del algoritmo se traducen en 2100 operaciones.

El mensaje se divide en bloques y se aplican sobre cada bloque operaciones de confusión


(sustituciones) y difusión (transposiciones). Haciendo demasiado costoso (en tiempo de
computación) extraer relaciones estadísticas entre texto claro, texto cifrado y clave.

Rijndael

Acrónimo formado por los nombres de sus dos autores Joan Daemen y Vincent Rijmen.

Trabajando en el COSIC lab (Bélgica) durante los años 1997-2000 los dos autores, diseñaron
un algoritmo de clave simétrica, y cifrado por bloques de tamaño variable (bloque mínimo: 128
bits). El algoritmo, tras un proceso de selección de cuatro años, se impuso como estándar de
encriptación para el FIPS en tres implementaciónes concretas: tamaño de bloque fijo de 128
bits, y tamaño de clave de 128, 192 o 256 bits.

El algoritmo está basado en una red de sustitución y permutación que se desarrolla en un


conjunto de iteraciones que ejecutan cuatro funciones invertibles diferentes formando tres
capas diseñadas para proporcionar resistencia frente a criptoanálisis lineal y diferencial.

- capa de mezcla lineal: ShiftRows y MixColumns permite obtener un alto nivel


de difusión a lo largo de varias rondas.
- capa no lineal: SubBytes, consiste en la aplicación de una S-Box, con
propiedades óptimas de no linealidad.
- capa de adición de clave: es una operación de XOR entre el estado
intermedio y la sub-clave correspondiente a cada iteración.
Qué hace el algoritmo
En primer lugar, y puesto que el AES es un algoritmo de cifrado por bloques, el mensaje
o bitstream se divide en bloques de cifrado. Los bloques de información de 128 bytes (el
algoritmo permite diferentes longitudes de bloque de cifrado, pero el aprobado por FIPS fija
el bloque en 128bits), con un byte como elemento direccionable, deberán sufrir diferentes
operaciones que pretenden enmascarar sus características estadísticas. Es decir, que
dificultarán un análisis criptográfico para romper el cifrado.

La clave de cifrado será, en este caso una matriz de 32 bytes. (para AES-128)

Durante el proceso, será necesario calcular las sub-claves de cifrado. Este cálculo supone la
extensión de la clave de cifrado inicial hasta 11 sub-claves parciales, de igual tamaño, que irán
utilizándose durante las iteraciones del algoritmo.

El flujo del algoritmo comienza al realizar la primera iteración diferente al resto. Luego, nueve
iteraciones idénticas y finalmente la última iteración final, también distinta. Las operaciones que
se realizarán pueden verse a continuación.
Se observa una ronda inicial en la que únicamente se efectúa una
operación de RoundKey, entre matriz de estado y sub-clave (en éste punto
la matriz de estado coincide con el bloque a cifrar, y la sub-clave, coincide
con la clave de encriptación). Seguidamente se entra en un bucle de 9
iteraciones donde se repiten 4 procesos. Por último la última iteración no
efectúa la operación de MixColumns.

A lo largo de todo el proceso, el bloque de información a cifrar ira sufriendo cada operación y
para describir su estado en cada instante del proceso se define la matriz de estado. Llamada
State en el estándar, será la matriz que albergue los resultados parciales del proceso, mientras
éste avanza. Los métodos descritos en la figura anterior consisten en:

RoundKey: XOR byte a byte entre matriz de estado y sub-clave de ronda.


SubBytes: Sustitución byte a byte, entre elementos de la matriz de estado y elementos de
la matriz de difusión S-Box. El valor del nibble más significitivo de cada byte define la fila del
elemento de S-Box. Y el valor del nibble menos significativo, determinará la columna. Así cada
byte se interpreta como la dirección de otro byte, presente en la matriz S-Box.
ShiftRows: Rotación de los elementos de cada fila de la matriz de estado, tantas veces como
el número de fila, hacia la izquierda.
MixColumns: Consiste en una multiplicación dentro de GF(28) módulo x4+1, entre los vectores
columnas de la matriz de estado, y el polinomio a(x)={03}x3+{01}x2+{01}x+{02}.

Particularidades a las operaciones basada en GF(28)

Cada columna es considerada un elemento perteneciente a GF(28), y cada byte, es también


considerado como un elemento perteneciente a GF(28), usando notación polinomial. Los
elementos basados en Cuerpos Finitos, pueden sumarse y multiplicarse, tal y como se describe
a continuación:

Suma: XOR sobre modulo 2: 1+1=0, 1+0=1, 0+1=1, 0+0=0,

Multiplicación: es algo mas compleja sobre Cuerpos de Galois (28). La multiplicación


opera columna a columna de la matriz de estado, considerando cada columna como
un polinomio de 4 elementos pertenecientes a GF(28). En MixColumns() se multiplican
por el polinomio a(x)={03}x3+{01}x2+{01}x+{02} módulo x4+1, asegurando así que
cualquier resultado de una multiplicación siempre podrá albergarse en una matriz
estado de 128 bits.

La operación de multiplicación de cada columna de la matriz de estado, por el polinomio


a(x) puede interpretarse como una multiplicación matricial. Resultando cada elemento
de la columna resultado, en el siguiente sistema de ecuaciones:

S’0 = ({02} S0) ({03} S1) S2 S3


S’1 = S0 ({02} S1) ({03} S2) S3
S’2 = S0 S1 ({02} S2) ({03} S3)
S’3 = ({03} S0) S1 S2 ({02} S 3)

Dentro de la operación de multiplicación de columnas por la matriz anterior, deberán


multiplicarse polinomios pertenecientes al GF(28) modulo polinomio irreducible de grado
8 descrito por:

f(x) = x8 + x4 + x3 + x + 1 o bien {011b} en notación polinomial


Las características de la reducción a modulo 8 aseguran que el resultado de la
multiplicación polinomial resultará en un polinomio de grado igual o inferior a 8, y por
ello, representable en un único byte.

Pero, no es así como se suelen implementar los algoritmos de la función MixColumns().


Puesto que se explota una particularidad debida al polinomio irreducible escogido en
AES. Al multiplicar por x ({02} en notación hexadecimal) resulta que el proceso de
multiplicación puede igualarse a la implementación de un shift register a la izquierda
y un XOR con la máscara {1b} (ésto último solo en caso de que el primer bit del
polinomio a multiplicar sea ‘1’ (equivale a que esté presente la potencia x7). Y puesto
que la operación de multiplicación es asociativa, la multiplicación de vectores se puede
transformar en una multiplicación sucesiva de por x.

Cálculo de Sub-claves
Cada sub-clave presenta el mismo tamaño que la clave de cifrado y el cálculo para cada una
de las 10 sub-claves que se deben definir, se realiza de la siguiente manera:

Para la 1ª columna de la clave iésima:


a. Rotación 1 vez de la ultima columna de la clave anterior.
b. SubBytes pero solo de los 4 bytes de esta columna.
c. XOR con primera col de la clave anterior, y columna iésima de matriz Rcon.

Para el resto de columnas:


a. XOR columna anterior y columna equivalente en la sub-clave anterior.

Ejemplo práctico de cifrado


Para todas las operaciones que se realizarán a continuación se utilizará notación hexadecimal.
Cada byte se representará como una única entidad y las operaciones del algoritmo se llevan a
cabo sobre bytes.

Definamos una clave, a partir de la codificación ASCII (hex) de los siguientes caracateres:
UCM[esc], JLIP, IMLL y SECO. Dando lugar a la siguiente clave:

55 43 4D 1B

4A 4C 49 50

49 4D 4C 4C

53 45 43 4F

Y definamos también un mensaje a cifrar. En este punto puede ser interesante utilizar uno de
los mensajes que se suelen utilizar en criptoanálisis para observar como funciona un algoritmo
de encriptación, éstos son mensajes especiales como: todo ceros, todo unos, unos y ceros
alternando (0xAA), etc. En este caso parece interesante cifrar un mensaje con todo ceros, que
permita observar como la fases que introducen difusión y confusión impiden la distinción de
particularidades estadísticas en la frecuencia de caracteres en el mensaje cifrado.

00 00 00 00

00 00 00 00

00 00 00 00

00 00 00 00

Al comenzar el programa sera necesario calcular las sub-claves de cada iteración y cargar en
memoria la matriz de permutación y sustitución S-Box.
Iteración0: Comenzamos con la operación RoundKey que en esta iteración será la única
operación que deberá tener lugar. Al ser el primer paso, la sub-clave de iteración consiste en la
propia clave. Y la operación de XOR con el mensaje elegido resultará en la propia clave, debido
a que se ha elegido un mensaje con todos los bytes {00}..

Iteración1-9: En este punto, se efectuarán 4 funciones sobre la matriz de estado, siendo la


entrada de cada función, la salida del anterior.

SubBytes: Por ejemplo, el primer elemento de la matriz es {55}. Y se sustituye por el


elemento de la fila 5 y columna 5 de la matriz S-Box (vér apéndice) que es {FC}. Y así
sucesivamente con todos los elementos de la matriz de estado.

FC 1A E3 AF

D6 29 3B 53

3B E3 29 29

ED 6E 1A 84

ShiftRows: Rotamos la fila 1 (la primera fila sería la fila 0), una vez hacia la izquierda.
La segunda fila 2 veces y la tercera 3 veces.

D6 - 29 - 3B - 53 --> 29 - 3B - 53 - D6
3B - E3 - 29 - 29 --> 29 - 29 - 3B - E3
ED - 6E - 1A - 84 --> 84 - ED - 6E - 1A

MixColumns: En el algoritmo, la información es interpretada como elementos


pertenecientes a Cuerpos Finitos, y por lo tanto se definirán las siguientes operaciones.
Comencemos por la primera columna: FC - 29 - 29 - 84.

Para calcular el primer elemento de la primera columna resultado deberemos hacer:

S’0 = ({02} S0) ({03} S 1) S2 S3


Entonces:

S’0 *= {02} S0 = {02} {FC} = {0000 0010} {1111 1100} en su representaicón binaria.

Utilizando notación polynomial: x (x7+x6+x5+x4+x3+x2).

Del polinomio irreducible f(x) se extrae la base para x8: x8 = x4+x3+x+1 y entonces:

S’0 * = x8+x7+x6+x5+x4+x3 = (x4+x3+x+1)+x7+x6+x5+x4+x3 = x7+x6+x5+x2+x


S’0 * = {1110 0011} = {E3}

Seguimos con los términos: S’0 **= {03} S1 = {03} {29} = {0000 0011} {0010 1001} =
S’0 ** = (x+1) (x5+x3+1) = x6+x4+x+x5+x3+1=x6+x5+x4+x3+x+1= {0111 1011} = {7B}
Como ya se ha explicado, la suma en GF(28) corresponde a una XOR bit a bit, por lo que:

{E3} - 1110 0011


{7B} - 0111 1011
{29} - 0010 1001
{84} - 1000 0100
------------------------
S’0 ={E3} {7B} {29} {84} --> 0011 0101 = {35}

Seguimos con el segundo término de la columna: S’1 = S0 ({02} S 1) ({03} S2) S3

S’1 * = ({02} S1) = ({02} {29}) = x (x5+x3+1) = x6+x4+x = {0101 0010} = {52}
S’1 ** = ({03} S2) = ({03} {29}) = (x+1) (x5+x3+1) = x6+x5+x4+x3+x+1 = {0111 1011} = {7B}

S’1 = {FC} {52} {7B} {84} --> 0101 0001 = {51}

Seguimos con el tercer y cuarto término de la columna:

S’2 = S0 S1 ({02} S 2) ({03} S3)


S’3 = ({03} S0) S1 S2 ({02} S 3)

Pero ahora, vamos a hacer uso de una particularidad a la multiplicación entre polinomios dentro
de GF(28) y con el polinomio irreducible: multiplicar por x equivale a rotar hacia la izquierda y
(solo si está presente la potencia x7) hacer un XOR con {1B}. De manera que:

{02} {84} ; {84} << 1 = {0000 1000} ; XOR({08},{1B}) = {13}


{03} {84} = {02} {84} {84} = XOR({13},{84}) = {97}

{FC} - 1111 1100


{29} - 0010 1001
{52} - 0101 0010
{97} - 1001 0111
------------------------
S’2 = {FC} {29} {52} {97} --> 0001 0000 = {10}

{02} {FC} ; {FC} << 1 = {1111 1000} ; XOR({F8},{1B}) = {E3}


{03} {FC} = {02} {FC} {FC} = XOR({E3},{FC}) = {1F}

{1F} - 0001 1111


{29} - 0010 1001
{29} - 0010 1001
{13} - 0001 0011
------------------------
S’3 = {1F} {29} {29} {13} --> 0000 1100 = {0C}

Finalmente el resultado para la primera columna de la matriz estado, después de MixColumns()


será:

35

51

10

0C

Este proceso deberá repetirse de idéntica manera para las otras 3 columnas para finalizar el
proceso MixColumns(). La matriz de estado resultará:

35 BD 7D DD

51 FA 66 3C

10 5F 74 8A

0C FD 8A EB

RoundKey: Por último en esta iteración, falta efectuar la operación RoundKey, que
consiste en efectuar una operación de XOR (suma) entre la matriz de estado y la sub-clave de
esta ronda.

Cálculo de la sub-clave de ronda 2. Se debe rotar hacia la izquierda (según se encuentra la


siguiente tabla: hacia arriba) el vector columna.

50

4C

4F

1B

Someterlo a una operación SubBytes():

53

29

84

AF
Y finalmente sumar la primera columna de la clave, junto con la primera columna de la matriz
Rcon. Como ejemplo realizamos el cálculo para el primer elemento de la segunda columna

{53} - 0101 0011


{55} - 0101 0101
{01} - 0000 0001
------------------------
S’3 = {53} {55} {01} --> 0000 0111 = {07}

Dando como resultado, para todas los elementos de la columna:

07

63

CD

FC

Ahora para el resto de columnas de la sub-clave, será necesario realizar una XOR entre
elementos de la columna análoga de la clave anterior, y la anterior columna. Por ejemplo, para
nuestro caso la segunda columna de la sub-clave que estamos calculando sera la XOR de la
segunda columna de la clave con la última columna calculada.

43 07 = 44

4C 63 = 2F

4D CD = 80

45 FC = B9

Y la tercera y cuarta columnas:

4D 44 = 09

49 2F = 66

4C 80 = CC

43 B9 = FA
1B 09 = 12

50 66 = 36

4C CC = 80

4F FA = B5

Resultando la sub-clave de ronda en:

07 44 09 12

63 2F 66 36

CD 80 CC 80

FC B9 FA B5

Finalmente ya solo resta efectuar una RoundKey (XOR) entre la clave de ronda (esta última
clave calculada) y la matriz de estado. Resultando:

32 F9 74 CF

32 D5 00 0A

DD DF B8 0A

F0 44 70 5E

Bien, esta última matriz será tomará como punto de partida para volver a repetir la iteración
durante otras 8 vueltas más, hasta totalizar 9. Y pasar a la última iteración.

Itaración10: Todo se efectuará de manera idéntica a las anteriores iteraciones, salvo que no
se efectuará la función MixColumns.

Resultado Final.

La matriz estado, al final de la operación RoundKey con la Sub-Clave de la iteración 10, en la


que no se ha efectuado MixColumns, será el Bloque Cifrado:

68 E5 7B C5

80 1E 22 4B
87 C4 A2 F1

C7 7E D5 7E

La operación de cifrado ha finalizado el finalizado del Bloque de 16 bytes seleccionado en este


punto.

Validación de la implementación
El NIST distribuye una serie de vectores con texto plano y su correspondiente texto cifrado, que
permiten validar cualquier implementación del AES, en sus variantes de ancho de clave, 128,
192 y 256 bits. El archivo es un .zip que puede descargarse aquí.

Mejoras a la implementación
Debido a enorme uso que tiene, multitud de estudios se han centrado en cómo mejorar el ratio
instrucciones/bytes cifrados (también es común la unidad instrucciones/bloque cifrado).

Una iteración de AES se descompone en: - 16 instrucciones shift


- 16 operaciones máscaras
- 16 loads (SubBytes)
- 4 loads (RoundKey)
- 16 XOR
Totalizando: 68 instrucciones, siendo 20 loads y 48 integer, para cada iteración. Es decir 720
instrucciones (280 loads, 4 stores y 508 integer) para cada bloque cifrado.

Particularizando para una implementación en concreto (las publicaciones suelen centrarse


en AES-128 debido a su mayor difusión), es posible aprovechar características de algunos
procesadores concretos, o bien optimizando el espacio en los campos de cada instrucción para
unir instrucciones. Mejorando de esta manera la eficiencia de ejecución del algoritmo. Aunque
es importante resaltar que muchos de estos métodos no pueden utilizarse conjuntamente.

Por ejemplo la implementación Scaled-index loads, permite ahorrar 80 instrucciones. La


Second-byte instructions permite ahorrar 40 instrucciones. O incluso, combined load-
xor permite ahorrar 168 instrucciones. Para una comprensión detallada de estas mejoras, y
conocer muchas más, es interesante acudir a “New AES software speed records” (D.Bernstein
P. Schwabe) University of Illinois, Chicago, USA. (ver referencias).

Otro acercamiento al problema, no equivalente al análisis anterior, consiste en mejorar el ratio


ciclos/instrucción. Ratios típicos para arquitectura PowerPc rondan los 17 ciclos/byte cifrado,
algo menores para Sun UltraSPARC III y aún mas bajas para Intel Core 2 Quad y AMD Athlon
64 X2, donde rondan los 10 ciclos por byte codificado.

Dependiendo de las instrucciones características que cada familia de procesadores puede


ofertar, los métodos para mejorar el ratio ciclos/byte codificado, son diversos. Los procesadores
Intel, permiten tres instrucciones conenteros por ciclo y por el contrario únicamente un load por
ciclo, por lo que el método de ahorro consiste en el uso de registros especiales tipo XMM para
realizar operaciones minimanzo el uso de loads. Por el contrario la arquitectura AMD permite
dos instrucciones load por ciclo.

El estudio más actualizado que se ha podido localizar cifra las mejores implementaciones
lineales del algoritmo en algo cercano a los 15 ciclos/byte, y para implementaciones en paralelo
del algoritmo en torno a los 1 ciclo/byte. La siguiente figura muestra estos resultados.

(fuente)

Implementación sobre LabView


El algorimto Rijndael, comprende un número considerable de iteraciones. Y aun cuando le
presente documento definde la elaboración de los cálculos a mano, ésto carece de sentido a
partir de la primera iteración. Con objeto de ir comprobando las operaciones plasmadas en las
páginas anteriores, y de calcular el bloque cifrado final, ha sido necesario la implementación del
cifrado AES, en su version AES-128.

Se ha elegido LabView para la implementación, debido a la facilidad para desarrollar un GUI


intuitivo, junto con el código. A continuación se describen las funciones programadas.

GUI
El programa permite ir observando como se modifica la matriz de estado durante todo el
algoritmo.

Para la elaboración del programa ha sido necesario diseñar las siguientes funciones. El código
labview se adjunta. código

inicializa_sbox - Permite inicializar los 256 bytes de la S-Box, a partir de un


documento de texto alojado en wikipedia (ver referencias).

finite_field_mult_02 - Multiplica un polinomio GF(28) por {02} modulo f(x) = x8+x4+x3+x+1.


Ver la siguiente figura.
Función: finite_field_mult_02. El .vi se adjunta

finite_field_mult_03 - Multiplica un polinomio GF(28) por {03} modulo f(x) = x8+x4+x3+x+1.

mix_columns - Multiplica un vector de 4 bytes GF(28) por a(x) módulo f(x) = x4+1.

Función: mix_columns. El .vi se adjunta.

shiftrows - Realiza el método ShiftRows descrito en el algoritmo.

subbytes_sbox - Realiza el método SubBytes descrito en el algoritmo.


Función subbytes_sbox. El .vi se adjunta.

Conclusiones
Después de su publicación, el mercado pronto adoptó particularmente rápido el estándar
AES para proteger comunicaciones. Actualmente hay 1462 implementaciones validadas por
NIST (National Institute of Standards and Technology). Y en gran parte se debe a una óptima
combinación de seguridad frente a eficiencia. Un análisis del coste computacional de AES,
frente otros estándares, puede observarse a continuación.

(fuente)
Referencias
1. Publicacion FIPS: Official AES Standard

2. “Criptografía y Seguridad de Computadores” - M.J. Lucena, Universidad de de Jaén,


2009.

3. AES S-Box

4. Lista de implementación aprovadas por NIST

5. Vectores Test aportados por NIST

6. “New AES software speed records” (D.Bernstein P. Schwabe) University of Illinois,


Chicago, USA.

7. Presentación: Käsper Schwabe How fast is AES?

You might also like