GolfScript, 60 символов
{[[0 1{.283{1$2*.255>@*^}:r~^}255*].@?~)={257r}4*99]{^}*}:S;
Этот код определяет именованную функцию, Sкоторая принимает байт и применяет к ней S-блок Rijndael. (Он также использует внутреннюю вспомогательную функцию с именем, rчтобы сохранить несколько символов.)
Эта реализация использует таблицу логарифма для вычисления GF (2 8 ) обратно, так как предложенный Томасом Pornin . Чтобы сохранить несколько символов, вся логарифмическая таблица пересчитывается для каждого входного байта; несмотря на это, несмотря на то, что GolfScript является очень медленным языком в целом, этот код занимает всего около 10 мс для обработки байта на моем старом ноутбуке. Предварительный расчет таблицы логарифмов (as 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 (что соответствует многочлену редукции 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 +-для создания четыре битовых-повернутой копии перевернутого входного байта. Все они собраны в массив вместе с константой 99 = 0x63, и XORed вместе для получения окончательного результата.