GolfScript, 60 символів
{[[0 1{.283{1$2*.255>@*^}:r~^}255*].@?~)={257r}4*99]{^}*}:S;
Цей код визначає функцію з назвою, S
яка бере байт і застосовує до неї S-поле Rijndael. (Також використовується внутрішня допоміжна функція, імені r
для збереження кількох символів.)
Ця реалізація використовує таблицю логарифмів для обчислення обертів GF (2 8 ), як це запропонував Томас Порнін . Щоб зберегти кілька символів, вся таблиця логарифмів перераховується на кожен вхідний байт; тим не менше, і незважаючи на те, що GolfScript взагалі дуже повільна мова, цей код займає лише близько 10 мс для обробки байта на моєму старому ноутбуці. Попередній розрахунок таблиці логарифмів (як L
) прискорює його до приблизно 0,5 мс на байт, за скромної вартості ще трьох символів:
[0 1{.283{1$2*.255>@*^}:r~^}255*]:L;{[L?~)L={257r}4*99]{^}*}:S;
Для зручності ось простий тестовий джгут, який викликає функцію S
, визначену вище, для обчислення та виведення всього S-вікна в шістнадцятковій формі, як у Вікіпедії :
"0123456789abcdef"1/:h; 256, {S .16/h= \16%h= " "++ }% 16/ n*
Спробуйте цей код в Інтернеті.
(Демонстрація в Інтернеті заздалегідь обчислює таблицю логарифмів, щоб уникнути занадто багато часу. Навіть так, веб-сайт GolfScript іноді може випадково вичерпатися; це відома проблема із сайтом, і перезавантаження зазвичай виправляє його.)
Пояснення:
Почнемо з розрахунку таблиці логарифмів, а конкретно з хелперної функції r
:
{1$2*.255>@*^}:r
Ця функція займає два входи в стек: байт і скорочувальна бітова маска (константа між 256 і 511). Він дублює вхідний байт, помножує копію на 2 і, якщо результат перевищує 255, XOR розміщує її за допомогою бітової маски, щоб повернути її назад під 256.
У коді генеруючого коду журнальної таблиці функція r
викликається бітовою маскою скорочення 283 = 0x11b (що відповідає поліному скорочення GF Rijndael GF (2 8 ) x 8 + x 4 + x 3 + x + 1), а результат XORed з початковим байтом, ефективно помноживши його на 3 (= x + 1, як многочлен) у кінцевому полі Ріндгаеля. Це множення повторюється 255 разів, починаючи з байта 1, і результати (плюс початковий нульовий байт) збираються в масив 257 елементів, L
який виглядає приблизно так (середня частина опущена):
[0 1 3 5 15 17 51 85 255 26 46 ... 180 199 82 246 1]
Причина, чому існує 257 елементів, полягає в тому, що, маючи попередньо встановлений 0 і 1, що виникає двічі, ми можемо знайти модульну інверсію будь-якого заданого байта, просто переглянувши його (нульовий) індекс у цьому масиві, відкинувши його та переглянувши вгору байт на індекс заперечення в тому ж масиві. (У GolfScript, як і у багатьох інших мовах програмування, індекси негативного масиву відлічуються назад від кінця масиву.) Дійсно, саме це робить код L?~)L=
на початку функції S
.
Решта коду викликає функцію помічника r
чотири рази за допомогою зменшення бітової маски 257 = 2 8 + 1 для створення чотирьох бітових повернених копій інвертованого вхідного байта. Всі вони збираються в масив разом з постійною 99 = 0x63 і XORed разом, щоб отримати кінцевий результат.