|
Funções da Inversa |
Na implementação da consulta à tabela é essencial que a única etapa não linear ( ByteSub ) seja a primeira transformação na rodada e que as linhas estejem deslocadas antes que MixColumn seja aplicada.
No inverso de uma rodada, a ordem das transformações na rodada é invertida, e conseqüentemente a etapa não-linear será a ultima a ser realizada, e as linhas são deslocadas após a aplicação da inversa de MixColumn.
Dessa forma a inversa de uma rodada não poderá ser implementada usando consulta à tabela.
Este detalhe foi previsto no projeto. A estrutura de Rijndael é tal que a seqüência das transformações da inversa é igual àquela da encriptação, apenas com as transformações substituídas pelas suas inversas e por uma mudança na keyschedule. Isto será mostrado a seguir.
Para mostrar como e porque a ordem das transformações foram alteradas usamos uma versão de Rijndael de 2 rodadas.
A inversa da rodada é dada por:
InvRound(State,RoundKey)
{
AddRoundKey(State,RoundKey);
InvMixColumn(State);
InvShiftRow(State);
InvByteSub(State);
}
A inversa da rodada final é dada por:
InvFinalRound(State,RoundKey)
{
AddRoundKey(State,RoundKey);
InvShiftRow(State);
InvByteSub(State);
}
A inversa da versão de Rijndael de 2 rodadas será a inversa da rodada final seguida da inversa da rodada. Assim temos:
AddRoundKey(State,ExpandedKey+2*Nb);
InvShiftRow(State);
InvByteSub(State);
AddRoundKey(State,ExpandedKey+Nb);
InvMixColumn(State);
InvShiftRow(State);
InvByteSub(State);
AddRoundKey(State,ExpandedKey);
Propriedades Algébricas
I ) A ordem de ShiftRow e ByteSub são indiferentes. ShiftRow simplesmente desloca os bytes e não tem nenhum efeito nos valores destes.
ByteSub processa os bytes individualmente, independente de sua posição.
I I ) A seqüência:
AddRoundKey(State,RoundKey);
InvMixColumn(State);
poder se substituída por:
InvMixColumn(State);
AddRoundKey(State,InvRoundKey);
com o InvRoundKey obtido aplicando InvMixColumn às RoundKey correspondente.
Isto é baseado no fato de que para uma transformação linear A, nós temos A(x + k) = A(x) + A(k).
Usando as propriedades descritas acima a inversa da versão de Rijndael de 2 rodadas será:
AddRoundKey(State,ExpandedKey+2*Nb);
InvByteSub(State);
InvShiftRow(State);
InvMixColumn(State);
AddRoundKey(State,I_ExpandedKey+Nb);
InvByteSub(State);
InvShiftRow(State);
AddRoundKey(State,ExpandedKey);
Observa-se agora que a estrutura é a mesma do Encriptador, e assim pode ser generalizado para qualquer número de rodadas então temos:
I_Round(State,I_RoundKey)
{
InvByteSub(State);
InvShiftRow(State);
InvMixColumn(State);
AddRoundKey(State,I_RoundKey);
}
I_FinalRound(State,I_RoundKey)
{
InvByteSub(State);
InvShiftRow(State);
AddRoundKey(State,RoundKey0);
}
A inversa do encriptador Rijndael fica:
I_Rijndael(State,CipherKey)
{
I_KeyExpansion(CipherKey,I_ExpandedKey) ;
AddRoundKey(State,I_ExpandedKey+ Nb*Nr);
For( i=Nr-1 ; i>0 ; i-- ) Round(State,I_ExpandedKey+ Nb*i) ;
FinalRound(State,I_ExpandedKey);
}
|
I_KeyExpansion() |
É feita usando a KeyExpansion() e aplicando InvMixColumn() em todas às chaves de rodadas exceto na primeira e na última. em pseudo código fica:
I_KeyExpansion(CipherKey,I_ExpandedKey)
{
KeyExpansion(CipherKey,I_ExpandedKey);
for( i=1 ; i < Nr ; i++ )
InvMixColumn(I_ExpandedKey + Nb*i) ;
}
|
InvByteSub() |
É a substituição de bytes usando a tabela inversa da já descrita. Abaixo é ilustrado a tabela inversa:

|
InvShiftRows() |
É um deslocamento cíclico das 3 últimas linhas em Nb-C1, Nb-C2 e Nb-C3 bytes respectivamente, de modo que o byte na posição j na linha i se mova para posição ( j + Nb-Ci) mod Nb.
|
InvMixColumns() |
A inversa de MixColumn é similar a MixColumn. Cada coluna é transformada multiplicando-a por um polinômio d(x), definido por :
( 03h x3 + 01h x2 + 01h x + 02h ) x d(x ) = 01h
resolvendo temos:
d(x) = 0Bh x3 + 0Dh x2 + 09h x + 0Eh