GolfScript, 60 caracteres
{[[0 1{.283{1$2*.255>@*^}:r~^}255*].@?~)={257r}4*99]{^}*}:S;
Este código define una función llamada S
que toma un byte y le aplica el S-box de Rijndael. (También usa una función auxiliar interna llamada r
para guardar algunos caracteres).
Esta implementación utiliza una tabla de logaritmos para calcular los inversos GF (2 8 ), como lo sugiere Thomas Pornin . Para guardar algunos caracteres, se recalcula toda la tabla de logaritmos para cada byte de entrada; aun así, y a pesar de que GolfScript es un lenguaje muy lento en general, este código solo tarda unos 10 ms en procesar un byte en mi computadora portátil anterior. Precalcular la tabla de logaritmo (as L
) la acelera hasta aproximadamente 0,5 ms por byte, con el modesto costo de tres caracteres más:
[0 1{.283{1$2*.255>@*^}:r~^}255*]:L;{[L?~)L={257r}4*99]{^}*}:S;
Por conveniencia, aquí hay un arnés de prueba simple que llama a la función S
, como se definió anteriormente, para calcular e imprimir todo el cuadro S en hexadecimal como en Wikipedia :
"0123456789abcdef"1/:h; 256, {S .16/h= \16%h= " "++ }% 16/ n*
Prueba este código en línea.
(La demostración en línea calcula previamente la tabla de logaritmos para evitar tomar demasiado tiempo. Aun así, el sitio en línea de GolfScript a veces puede expirar al azar; este es un problema conocido con el sitio, y una recarga generalmente lo soluciona).
Explicación:
Comencemos con el cálculo de la tabla de logaritmo, y específicamente con la función auxiliar r
:
{1$2*.255>@*^}:r
Esta función toma dos entradas en la pila: un byte y una máscara de bits de reducción (una constante entre 256 y 511). Duplica el byte de entrada, multiplica la copia por 2 y, si el resultado excede 255, lo XOR con la máscara de bits para devolverlo a 256.
Dentro del código de generación de la tabla de registro, la función r
se llama con la máscara de bits de reducción 283 = 0x11b (que corresponde al polinomio de reducción Rijndael GF (2 8 ) x 8 + x 4 + x 3 + x + 1), y el resultado es XORed con el byte original, multiplicándolo efectivamente por 3 (= x + 1, como polinomio) en el campo finito de Rijndael. Esta multiplicación se repite 255 veces, comenzando desde el byte 1, y los resultados (más un byte inicial cero) se recopilan en una matriz de 257 elementos L
que se ve así (se omite la parte central):
[0 1 3 5 15 17 51 85 255 26 46 ... 180 199 82 246 1]
La razón por la que hay 257 elementos es que, con el 0 antepuesto y con 1 ocurriendo dos veces, podemos encontrar el inverso modular de cualquier byte dado simplemente buscando su índice (basado en cero) en esta matriz, negándolo y mirando arriba el byte en el índice negado en la misma matriz. (En GolfScript, como en muchos otros lenguajes de programación, los índices de matriz negativos cuentan hacia atrás desde el final de la matriz). De hecho, esto es exactamente lo que hace el código L?~)L=
al comienzo de la función S
.
El resto del código llama a la función auxiliar r
cuatro veces con la máscara de bits de reducción 257 = 2 8 + 1 para crear cuatro copias rotadas en bits del byte de entrada invertido. Todos estos se recopilan en una matriz, junto con la constante 99 = 0x63, y se juntan XOR para producir la salida final.