GolfScript, 60 caracteres
{[[0 1{.283{1$2*.255>@*^}:r~^}255*].@?~)={257r}4*99]{^}*}:S;
Esse código define uma função nomeada S
que recebe um byte e aplica a caixa S de Rijndael. (Ele também usa uma função auxiliar interna chamada r
para salvar alguns caracteres.)
Essa implementação usa uma tabela de logaritmo para calcular os inversos GF (2 8 ), conforme sugerido por Thomas Pornin . Para salvar alguns caracteres, toda a tabela de logaritmos é recalculada para cada byte de entrada; mesmo assim, e apesar do GolfScript ser uma linguagem muito lenta em geral, esse código leva apenas 10 ms para processar um byte no meu laptop antigo. O pré-cálculo da tabela de logaritmo (as L
) acelera-a para cerca de 0,5 ms por byte, ao custo modesto de mais três caracteres:
[0 1{.283{1$2*.255>@*^}:r~^}255*]:L;{[L?~)L={257r}4*99]{^}*}:S;
Por conveniência, aqui está um equipamento de teste simples que chama a função S
, conforme definido acima, para calcular e imprimir toda a caixa S em hexadecimal, como na Wikipedia :
"0123456789abcdef"1/:h; 256, {S .16/h= \16%h= " "++ }% 16/ n*
Experimente este código online.
(A demonstração on-line pré-calcula a tabela de logaritmo para evitar muito tempo. Mesmo assim, o site GolfScript on-line às vezes pode exceder o tempo limite; esse é um problema conhecido do site, e uma atualização geralmente o corrige.)
Explicação:
Vamos começar com o cálculo da tabela de logaritmos e, especificamente, com a função auxiliar r
:
{1$2*.255>@*^}:r
Essa função recebe duas entradas na pilha: um byte e uma máscara de bits de redução (uma constante entre 256 e 511). Duplica o byte de entrada, multiplica a cópia por 2 e, se o resultado exceder 255, XORs com a máscara de bits para trazê-lo de volta para 256.
Dentro do código de geração da tabela de log, a função r
é chamada com a máscara de bits de redução 283 = 0x11b (que corresponde ao polinômio de redução de Rijndael GF (2 8 ) x 8 + x 4 + x 3 + x + 1) e o resultado é XOR com o byte original, multiplicando-o efetivamente por 3 (= x + 1, como um polinômio) no campo finito de Rijndael. Essa multiplicação é repetida 255 vezes, iniciando no byte 1, e os resultados (mais um byte zero inicial) são coletados em uma matriz de 257 elementos L
que se parece com isso (parte do meio omitida):
[0 1 3 5 15 17 51 85 255 26 46 ... 180 199 82 246 1]
A razão pela qual existem 257 elementos é que, com o 0 precedido e o 1 ocorrendo duas vezes, podemos encontrar o inverso modular de qualquer byte dado simplesmente pesquisando seu índice (com base em zero) nessa matriz, negando-o e procurando o byte no índice negado na mesma matriz. (No GolfScript, como em muitas outras linguagens de programação, os índices negativos da matriz contam para trás a partir do final da matriz.) Na verdade, é exatamente isso que o código L?~)L=
no início da função S
faz.
O restante do código chama a função auxiliar r
quatro vezes com a máscara de bit de redução 257 = 2 8 + 1 para criar quatro cópias com rotação de bits do byte de entrada invertido. Todos eles são coletados em uma matriz, juntamente com a constante 99 = 0x63, e XORed juntos para produzir a saída final.