Comments 4
По поводу части c умножением полиномов над полем Галуа.
В поле у операции сложения есть обратная - вычитание, но у них совпадают таблицы и они обе для битов реализуются исключающим ИЛИ (xor). Из-за того, что вы упустили этот момент начинается путаница, когда вы объясняете реализцию
GF_mul
.GF_mul
у вас на каждом шаге домножает полином a
на и его степень сравнивается с 8. Если у получившегося полинома степень 8 (а больше быть не может, т.к. умножение на
увеличивает степень ровно на 1), то он берётся по модулю используемого неприводимого полинома
p = 0x01C3
. Но из того, что степень a
равна 8 следует, что в делении будет ровно один шаг, т.е. a = p + (a mod p)
и для того, чтобы найти модуль ваш код вычитает p
из a
: (a mod p) = a - p
.
Таким образом получаем оптимизацию производительности: долгая операция деления полиномов с остатком свелась к быстрой операции вычитания. Для машины это будет побитовый xor. К возвращению в поле это отношения не имеет, да и выйти из него в рамках однобайтовой переменной невозможно.
Ну и наверное стоит упомянуть, что верхние байты в записях p
и a
не хранятся, а только подразумеваются.
P.S.: Есть какая-то конкретная причина, по которой вы решили не пользоваться встроенным хабровским редактором и вставить формулы рисунками?
Вообще, можно добивать сообщение не 0xFF до кратного, а 0x00, тогда не нужно будет считать и хранить количество добавочных нулей, потому что при дешифровке не будет повреждения последовательности. Но тогда надо будет немного повозиться с тем, как хранить это в файлах, потому что 0x00 - это служебный символ
Для симметричных блочных шифров обычно используют стандарт PKCS#7: добавляют до конца блока n
байтов со значением n
, а если сообщение выровнено, добавляют целый блок по этому же правилу для однозначности расшифровки.
Вообще есть много вариантов.
TL;DR
Реализация ГОСТ 32.12. Симметричный шифр Кузнечик