О чем статья
На просторах интернета есть несколько статей об алгоритме получения хеш-функции Стрибог (ГОСТ 34.11-2012), в том числе и на Хабре. Однако везде в качестве примера приводится реализация на языках программирования C, C#, Python и других. То есть идет последовательное выполнение операций алгоритма. В данной статье я хочу затронуть аппаратную реализацию на языке System Verilog, уделить внимание распараллеливанию вычислений и описанию интерфейсов модулей. Для начала кратко рассмотрим теорию.
Краткая теория
Основу алгоритма составляют последовательное исполнение так называемой g функции и функции сложения в кольце. Структурную схему можно увидеть на рисунке 1. Подробную теорию и математическое описание можно почитать в ГОСТ 34.11—2012 или в этой статье. Мы же рассмотрим, что подается на вход и получается на выходе. А далее рассмотрим практическую реализацию.
Сложение в кольце
На рисунке обозначено sc(a,b). В данной функции 512-разрядный вход а складывается с 512-разрядным входом b, результат пишется в 512 разрядный выход s. Если есть переполнение, то оно отбрасывается.
G функция
На рисунке обозначено g(m,h,n).
m – это входной массив данных, для которого считается хеш-функция, разбитый по 512 бит. Если последний кусочек меньше 512 бит, то оно сразу дополняется нулями с единичкой в первом дополнительном разряде до полных 512 бит;
h – это выход функции от предыдущей итерации, если итерация первая, то подается инициализационное значение V0 = `{64{8`h00}} или V0 = `{64{8`h01}} ;
n – количество бит исходного сообщения в 512 битном кусочке. Для целого кусочка значения будет 512 бит;
Если исходный массив больше 512 бит, то вычисления состоят из трех этапов :
Инициализация
Рекурсия
Дополнение
Если исходный массив меньше или равен 512 бит, то вычисления состоят из двух этапов :
Инициализация
Дополнение
Хеш-функция «Стрибог» может иметь две реализации с результирующим значением длиной 256 или 512 бит. Для реализации 512 бит на этапе инициализации V0 = `{64{8`h00}}, для реализации 256 бит на этапе инициализации V0 = `{64{8`h01}}, а c выхода последней g функции берутся старшие 256 бит.
Рассмотрим внутреннее устройство g функции. Структурная схема представлена на рисунке 2. Данная функция состоит из LPSX функций и операций исключающего “ИЛИ”. Кроме того, используется массив итерационных констант, который используется для входного аргумента b функции LPSX на итерациях с 1 по 12. Значения констант из массива приведено в ГОСТ 34.11-2012.
LPSX-функция
Структурная схема представлена на рисунке 3. Функция LPSX представляет из себя алгоритм преобразования и перестановки байт, который можно реализовать последовательно через функции X,S,P,L про которые можно подробно почитать здесь или здесь. Преобразования S и L можно выполнить заранее и сформировать восемь массивов по 256 восьмибайтовых чисел, в которых будут содержаться все возможные значения этих двух преобразований. Помимо этого, при вычислении хеш‑суммы с использованием заранее рассчитанных значений можно сразу сделать и нужные перестановки в соответствии с преобразованием P. Таким образом последовательные преобразования LPSX можно заменить одним преобразованием PRECALC с массивом заранее расчитанных значений.
Аппаратная реализация
Распараллеливание вычислений
В отличие от программной реализации, аппаратная реализация в ПЛИС или ASIC позволяет распараллеливать вычисления. Так, на верхнем уровне параллельно и независимо друг от друга в каждой итерации производятся вычисления в двух функциях суммирования по модулю 2 и вычисление g функции. Если посмотреть на структурную схему реализации g функции, то можно заметить, что вычисление LPSX функций от входа n и массива констант C идет независимо от вычисления LPSX функций от входа m (см. рисунок 2). Следовательно, при вычислении g функции можно создать два экземпляра LPSX функций, которые будут работать параллельно, производя по 12 итераций до получения выходного значения g функции. Схематично такая реализация представлена на рисунке 4.
Описание интерфейсов
Для каждой функции приведу интерфейс для реализации на языке описания аппаратуры Verilog или VHDL, а также диаграмму сигналов.
LPSX-функция
Представляет из себя регистровый конвейер вычислений. На вход подаются данные и сигнал валидности. На выходе преобразованные данные и сигнал валидности.
G функция
Представляет из себя регистровый конвейер вычислений. На вход подаются данные и сигнал валидности. На выходе преобразованные данные и сигнал валидности.
Функция сложения в кольце
Представляет из себя регистровый конвейер вычислений. На вход подаются данные и сигнал валидности. Поскольку идет суммирование входного числа с результатом предыдущего вычисления, то удобнее оставить один вход данных и добавить сигнал очистки модуля clear_i.
Модуль верхнего уровня
Представляет из себя регистровый конвейер вычислений. На модуль приходят 5 групп сигналов:
системные – частота и сброс
настройки – выбор длины хеша
входные данные – данные с рукопожатием valid/ready, а также флаг последнего сообщения и количество значимых бит в последнем сообщении
управление – запрос на старт работы автоматов модуля и подтверждение выставляемое после получения хеша
-
выходные данные — данные с рукопожатием valid/ready
Заключение. Описание исходников
Исходные файлы хеш-функции Стрибог на языке System Verilog находятся в моем репозитории git. Также там представлен тестбенч с примерами из ГОСТа. Для запуска симуляции в программе QuestaSim необходимо выполнить:
в консольном режиме для реализации без предвычислений,
make run_questa_console
в консольном режиме для реализации c предвычислениями,
make precalc=1 run_questa_console
в графическом режиме для реализации без предвычислений,
make run_questa_gui
в графическом режиме для реализации c предвычислениями.
make precalc=1 run_questa_gui
Комментарии (19)
aystarik
02.04.2024 02:39smod2(a,b) -- это разве не xor?
rvvernin Автор
02.04.2024 02:39В данном случае это операция сложения в кольце, если брать формулировку из ГОСТ. Но в целом вы правы суммирование по модулю 2 это XOR. Я поправил статью, теперь более корректное название функции. Спасибо за замечание.
aystarik
02.04.2024 02:39вроде как и в стрибоге это xor -- по вашей ссылке на c++ реализацию...
"X-преобразование. На вход функции X подаются две последовательности длиной 512 бит каждая, выходом функции является XOR этих последовательностей."
rvvernin Автор
02.04.2024 02:39X преобразование входит в LPSX функцию (рис. 3). У меня это обозначено как XOR(a,b). А кольцевое суммирование идёт на верхнем уровне (рис. 1) . В статье на которую ссылаетесь это ... "
5.Вычислить N = (N + |M|) mod 2 512
6.Вычислить Σ = (Σ + m) mod 2 512 "
deafcafe
02.04.2024 02:39В 2013 на Delphi дипломную работу делал, Стрибог, подпись на тестовых эллиптических кривых (512-битная), сейчас флешбек словил.
bk_space
02.04.2024 02:39Здорово!
Единственное, что пока вызывает вопросы - верификация. Наверное, 4х примеров из госта, как в ващем тестбенче, не хватит чтобы полноценно верифицировать блок.
Но тогда наверное придётся подумать как нагенерировать еще валидных примеров (есть ли код, например на C, в правильности которого уже никто не станет сомневаться)?
Автору успехов)
rvvernin Автор
02.04.2024 02:39Согласен. Здесь речь идет не о верификации, а лишь о первичной проверки работоспособности. Для верификации необходима, так называемая, gold model (например на C или на несинтезируемых конструкция system verilog), с которой можно сранивать результаты. Причем правильно если написанием rtl и верификацией занимаются разные люди.
Brak0del
Круто! Если не секрет, какие получились характеристики: сколько оно заняло по ресурсам (ПЛИС), на какой частоте, какую производительность в МБ/с имеет?
mpa4b
И ещё бы хорошо в сравнении с более традиционными хешами, например sha256/sha512, ну и например sha3, skein, blake.
iDoka
Имплементировал его во времена лихорадки.
Если вам нужен результат каждый такт (конвейер), то хэша хуже Стрибога придумать сложно.
Процитирую себя самого же с Электроникса:
Brak0del
Интересная инфа, спасибо!
mpa4b
Лично я не знаю традиционного криптохеша, который мог бы принимать данные каждый такт. Ну кроме читов вроде буферизации по 1 байтику или всяких распараллеливаний по 4к или деревом. А вот штуки, пригодные только для MACа, типа того, что в aes-gcm или chacha20-poly1305 -- теоретически (и зачастую практически) могут. Но они не полноценные хеши.
Brak0del
В примере из Электроникса, насколько понимаю, ограниченная постановка: хэшируют блоки фиксированной длины 64 байта, а не произвольной.
mpa4b
Ну, если хешировать куски данных размером в 1 блок хеша, тогда конечно можно. Но это бессмысленно, т.к. обычно хешируются всё же сообщения в несколько блоков хеша. Иногда в очень много.
mpa4b
А если логикой?
rvvernin Автор
Синтезизировал данный модуль в вивадо для ПЛИС xcvu19p-fsva3824-2-e, по ресурсам получилась следующая картинка.
По частоте синтез проходит на 400 МГц. Но в принципе можно и выше поднять у меня пока кольцевое суммирование идет за 1 такт, но там есть запас в 29 тактов на выполнение g - функции, и соответвенно суммирование можно конвейеризировать. В целом на вычисление хеша для одного 512 битного слова нужно 29 тактов в варианте с предвычислениями. По поводу производительности - это сильно зависит в целом от архитектуры системы - откуда, куда и как передаем данных.
Brak0del
Полезная инфа, спасибо!