ПРАКТИЧЕСКАЯ КРИПТОГРАФИЯ АЛГОРИТМЫ И ИХ ПРОГРАММИРОВАНИЕ



         

Листинг 4.3


Функция Feistel_Network() представляет собой реализацию сети Файстеля с произвольным числом раундов rounds. Ключ key представляет собой 8-битное значение, которое используется только как аргумент для передачи его функции гаммирования F_Gamma(). Обратите на это особое внимание, поскольку, очевидно, здесь таится первый способ оптимизации алгоритма.

Чтобы ускорить исполнение функции Feistel_Network(), мы можем внести тело функции F_Gamma() внутрь Feistel_Network(), устранив тем самым накладные расходы на передачу параметров и вызов подфункции. Другой очевидный способ ускорить процесс состоит в том, чтобы сделать число раундов постоянным (например, равным восьми или шестнадцати), а затем избавиться от цикла, расписав все итерации шифра последовательно, одну за другой. Выбор количества раундов объясняется нахождением некоторого своего рода компромисса между малой скоростью шифрования у шифра с большим количеством раундов и простотой вскрытия шифра с малым их числом. Этот показатель у шифра, построенного на сети Файстеля, колеблется от 8 до 32 раундов. Впрочем, никто не возбраняет применять и 64, и 128 раундов. Все упирается лишь в вычислительные мощности компьютерных систем. Единственное ограничение состоит в том, что количество раундов должно быть четным. В таком случае обе половинки - и левая, и правая - будут обработаны одинаковое число раз и, следовательно, не возникнет ситуации, когда одна половина данных (например, четная), зашифровываемых 16-раундовым алгоритмом, в действительности обработана восемью, а другая всего лишь семью итерациями алгоритма.

Все проделанные модификации для алгоритма с четырьмя раундами показаны в листинге 4.4. Подобная оптимизация обычно дает прирост производительности в 5 - 10%, а ведь это еще оптимизация не алгоритма, как такового, а примитивная оптимизация его реализации.

uint32_t Feistel_Network_Optimal(uint32_t data, uint8_t key, int rounds) { uint16_t left, right, swap; left = data & 0xFFFF; // делим данные на половинки right = (data >> 16) & 0xFFFF; swap = left ^ right ^ ((uint16_t) key * 0xABCD1234); // 1-й раунд left = right; right = swap; swap = left ^ right ^ ((uint16_t) key * 0xABCD1234); // 2-й раунд left = right; right = swap; swap = left ^ right ^ ((uint16_t) key * 0xABCD1234); // 3-й раунд left = right; right = swap; swap = left ^ right ^ ((uint16_t) key * 0xABCD1234); // 4-й раунд left = right; right = swap; return (left | ((uint32_t) right << 16)); }




Содержание  Назад  Вперед