Стандарти симетричного шифрування країн СНД на Python

image
Перші тижні нового року найкращий час для того, щоб затишно влаштувавшись біля віконця, згадати що ж нам приніс минулий рік.
А він приніс нам два нових стандарту шифрування. Російський стандарт ГОСТ Р 34.12-2015 (блочний шифр Коник). І український ДСТУ 7624:2014 (блочний шифр Калина). Холодними зимовими вечорами не можна упускати такий вдалий привід покодить. Під катом короткий опис алгоритмів та їх реалізація на Python. А щоб новим шифрів було веселіше, розбавимо їх суспільство білоруським СТБ 34.101.31-2007.

ГОСТ Р 34.12-2015

Почати пропоную з російського стандарту — блочного шифру Коник. Довжина вхідного блоку шифру — 128 біт, довжина ключа — 256 біт.
У шифрі використовуються наступні перетворення:
  • X — побітове додавання по модулю 2 з ключем:
  • Нелінійне перетворення S здійснюється заміною кожного байта підстановкою з таблиці π:
  • Лінійне перетворення L реалізується за допомогою множення над полем Галуа по модулю многочлена :
     Δ — відображення, сопоставляющее двійковій рядку елемент кінцевого поля.
    — відображення, сопоставляющее елемента кінцевого поля двійкову рядок.

    При обчисленні операції додавання і множення виробляються в кінцевому полі.

Процедуру зашифрування 128-бітного блоку a формально описується виразом:
.
Що в більш наочній формі виглядає так:


Раундові 128-бітові ключі K1, K2 виходять розбиттям основного 256-бітного ключа навпіл.
З їх допомогою обчислюються наступні раундові ключі:




При расшифровании використовуються зворотні перетворення:


Приклад використання Python:
if __name__ == '__main__':
mtest = list(binascii.unhexlify('1122334455667700ffeeddccbbaa9988'))
ktest = list(binascii.unhexlify('8899aabbccddeeff0011223344556677fedcba98765432100123456789abcdef'))
gost =gost2015(ktest)
print('GOST 34.12-2015')
print(datetime.datetime.now())
c = gost.encryption(mtest)
d = gost.decryption©
print(datetime.datetime.now())


ДСТУ 7624:2014

Введений у липні 2015 року як українського стандарту шифр Калина підтримує декілька варіантів довжини блоку і ключа. Тут я опишу версію шифру з довжиною блока і довжиною ключа дорівнює 128 біт.

Внутрішній стан шифру є матрицею з 8 рядами і 2 стовпцями. Перед початком шифрування матриця заповнюється байтами відкритого тексту. Потім над елементами матриці проводиться 10 раундів наступних перетворень.
  • — складання колонок матриці стану з колонками раундового ключем, представленого у вигляді матриці, по модулю 264.
  • (SubBytes) — заміна кожного байта матриці стану підстановкою з однієї з чотирьох таблиць π0, π1, π2, π3.
  • (SiftRows) — циклічний зсув вправо на одну позицію рядків з 4-го по 8-ю.
  • (MixColumns) — перетворення колонок матриці станів. Кожен елемент нової матриці обчислюється за формулою: , де ⊗ — скалярний добуток векторів, v — вектор, , Gj — колонка матриці. Операції множення і додавання проводиться в кінцевому полі по модулю многочлена
  • — побітове додавання по модулю 2 матриці внутрішнього стану шифру і раундового ключа Kv
Процес шифрування описується наступним виразом:

Або в більш наочному вигляді:

Для формування раундових ключів спочатку, використовуючи майстер-ключ До, обчислюється проміжний ключ :
, де для випадків, коли довжина блоку дорівнює довжині ключа.
Ключі для парних раундів генеруються на основі проміжного ключа:
, де i — номер раунду, а 0x01000100010001000100010001000100
Ключі для непарних раундів обчислюються так:
, де l — довжина блока.

При расшифровании використовуються зворотні перетворення:


Приклад використання Python:
if __name__ == '__main__':
key = list(binascii.unhexlify('000102030405060708090a0b0c0d0e0f'))
pt = list(binascii.unhexlify('101112131415161718191a1b1c1d1e1f'))
dstu =dstu2014(key)

key2 = list(binascii.unhexlify('0f0e0d0c0b0a09080706050403020100'))
ct = list(binascii.unhexlify('1f1e1d1c1b1a19181716151413121110'))
dstu2 = dstu2014(key2)

print(datetime.datetime.now())
c = dstu.encryption(pt)
d = dstu2.decryption(ct)
print(datetime.datetime.now())


СТБ 34.101.31-2007

Шифр BelT, який має довжину блоку 128 біт і довжину ключа 256 біт, був прийнятий стандарт симетричного шифрування республіки Білорусь в 2011 році. Шифрування здійснюється 8 раундами перетворень, застосованих до вхідного блоку.
Процедура зашифрування складається з наступних кроків:
  • Вхідний блок записується у вигляді image
  • Ключ записується у вигляді imageі визначаються раундові ключі
  • Додатковим змінним a, b, c, d присвоюються значення image

  • Де Gr — операція перетворення 32-бітної вхідний рядки і ; RotHir — циклічний зсув вліво на r біт; H(u) — операція заміни 8-бітної вхідний рядки підстановкою з таблиці; — операції додавання і віднімання за модулем 232.
  • imageповертається в якості шифртекста.
При расшифровании ті ж операції застосовуються в зворотному порядку.

Приклад використання Python:
if __name__ == '__main__':
key = list(binascii.unhexlify('E9DEE72C8F0C0FA62DDB49F46F73964706075316ED247A3739CBA38303A98BF6'))
belt1 = belt(key)
m = list(binascii.unhexlify('B194BAC80A08F53B366D008E584A5DE4'))

key2 = list(binascii.unhexlify('92BD9B1CE5D141015445FBC95E4D0EF2682080AA227D642F2687F93490405511'))
belt2 = belt(key2)
c = list(binascii.unhexlify('E12BDC1AE28257EC703FCCF095EE8DF1'))
print(datetime.datetime.now())
c1 = belt1.encryption(m)
d1 = belt2.decryption©
print(datetime.datetime.now())


PS

Реалізацію всіх описаних алгоритмів на Python можна знайти на GitHub.

Посилання

  1. Більш докладний опис шифру Коник наводиться і в цієї статті користувача ru_crypt, з якої я запозичив декілька ілюстрацій.
  2. Текст стандарту ГОСТ Р 34.12-2015 можна знайти на тут.
  3. Опис шифру Калина доступно тут.
  4. Стандарт СТБ 34.101.31-2007 лежить тут.


Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.