Funções de Encriptação |
Round(State,RoundKey)
{
ByteSub(State);
ShiftRow(State);
MixColumns(State);
AddRoundKey(State,RoundKey);
}
A rodada final é diferente e definida por
FinalRound(State,RoundKey)
{
ByteSub(State) ;
ShiftRow(State) ;
AddRoundKey(State,RoundKey);
}
State : Estado intermediário no processo de criptografia 4 linhas X Nb colunas, onde cada coluna representa 4 bytes.
S-BOX : Tabela não linear que faz a substituição do valor de cada byte.
Word : Grupo de 32 Bits ou array de 4 Bytes. Significa uma coluna de State.
K : chave criptografada secreta pode ter 128, 192, 256 bits.
Nk : No de colunas de K. Nk = 4 (AES-128), 6 (AES-192), 8 (AES-256). É calculado dividindo tamanho da chave por 32 bits.
Nb : No de colunas do State. Nb = 4, 6, 8. Similar a Nk.
Nr : No de rodadas, dado em função de Nb e Nk de acordo com a tabela
Nr |
Nb = 4 |
Nb = 6 |
Nb = 8 |
|
Nk = 4 |
10 |
12 |
14 |
|
Nk = 6 |
12 |
12 |
14 |
|
Nk = 8 |
14 |
14 |
14 |
|
ByteSub() |
Transformação que faz uma substituição de bytes no ESTADO, seguindo a tabela de substituição não linear (S-BOX), a qual é construída seguindo os passos:
1) Faz-se uma multiplicação inversa no GF(28), onde o 00h é mapeado para si mesmo.
2) Aplica a transformação bi’ = bi + b( i + 4 ) mod 8 + b( i + 5 ) mod 8 + b( i + 6 ) mod 8 + b( i + 7 ) mod 8 + ci onde 0<= i < 8 e bi é o bit do byte b e ci é o bit de 63h.
Para uma melhor visualização, os passos serão apresentados na forma matricial abaixo:

onde o indice 7 corresponde ao bit mais significativo do byte a ser substítuido
O que resulta na seguinte tabela:

onde x e y representa o byte em hexadecimal b = X Y h, o valor retornado será, pelo qual o byte b deverá ser substituído.
A figura abaixo mostra como é a transformação ByteSub(). S’r,c apresenta o byte substituído observando a tabela acima.

|
ShiftRow() |
As linhas da matriz STATE são ciclicamente deslocadas, onde a linha 0 não é deslocada e as linhas 1, 2, 3 são deslocada por C1, C2, C3 bytes respectivamente.
Os valores do deslocamento estão em função do tamanho do bloco e são descritos na tabela abaixo:

A figura abaixo ilustra a ShiftRow() em um bloco de 128 bits (Nb = 4) ou 192 bits (Nb = 6)
|
MixColumns() |
Cada coluna de um STATE é multiplicada módulo m(x) = x4 + 1 por um polinômio constante
p(x) = 03h x3 + 01h x2 + 01h x +02h
Na forma matricial com 0 =< c < Nb
E ilustrado a transformação em um estado de Nb=4

|
AddRoundKey() |
Uma RoundKey é adicionada ao ESTADO através de XOR.
A RoundKey é derivada da chave K através da Key Schedule() e possui tamanho (Nb) igual ao do ESTADO.
É ilustrada a operação onde o XOR é feito entre as colunas da chave e do ESTADO

|
KeySchedule() |
É feita seguindo os passos abaixo
Passo 1) No total de Round Keys = Tamanho do Bloco X ( No de rodadas + 1)
Passo 2) A chave K é expandida em KeyExpansion()
Passo 3) As RoundKey são extraidas da chave expandida de Nb em Nb words, ou seja a 1a roundkey usa as primeiras Nb words, a 2a as Nb seguintes e assim por diante.
|
KeyExpansion() |
ExpandedKey: É um array de words de 4 bytes cada e é denotada por W[Nb * (Nr +1)]. As primeiras Nk contém a chave K. As seguintes são recursivamente definidas em termos das de menor índice.
A KeyExpansion() depende do valor de Nk.
Para Nk<=6

Na descrição SubByte(W) faz a substituição dos bytes usando a S-BOX já descrita. A RotByte(W) retorna uma palavra na qual os bytes
são ciclicamente deslocados como: Se a entrada for (a,b,c,d) terá como saída (b,c,d,a).
Pode-se ver que as primeiras Nk words são feitas a partir da chave K. Cada word seguinte W[i] = EXOR ( ^ ) da word anterior W[i-1 ] e da word Nk posições anteriores W[i-Nk]. Para words em posições múltiplas de Nk, uma transformação é aplicada a W[i-1 ] antes do EXOR e uma constante de rodada é EXORed. Esta transformação consiste em um deslocamento cíclico dos bytes em uma word ( RotByte() ), seguido de uma consulta na tabela S-BOX de todos os 4 bytes da word ( SubByte() ).
Para Nk > 6

A diferença em relação a função para Nk<=6, é que para i-4 múltiplo de Nk, SubByte é aplicada à W[i-1 ] antes do EXOR.
As constantes de rodada são independentes de Nk e definidas pela função Rcon[ i ] como segue:
Rcon[i] = (RC[i],‘00’,‘00’,‘00’). onde RC[i] representa um elemento em GF(28) com um valor de X(i-1) tal que:
RC[1] = 1 e RC[ i ] = X * RC[i-1] = X(i-1) com X = 02h.
RoundKey :
As chaves de rodada ( RoundKey i ) são dadas pelo buffer de words de W[Nb*i] até W[Nb*(i+1)] como mostrado abaixo:

Pseudo Código do Criptografador
Rijndael(State,CipherKey)
{
KeyExpansion(CipherKey,ExpandedKey) ;
AddRoundKey(State,ExpandedKey);
For( i=1 ; i<Nr ; i++ ) Round(State,ExpandedKey + Nb*i) ;
FinalRound(State,ExpandedKey + Nb*Nr);
}
A KeyExpansion pode ser feita previamente e Rijndael pode ser especificado em termos da chave expandida.
Rijndael(State,ExpandedKey)
{
AddRoundKey(State,ExpandedKey);
For( i=1 ; i<Nr ; i++ ) Round(State,ExpandedKey + Nb*i) ;
FinalRound(State,ExpandedKey + Nb*Nr);
}