Академический Документы
Профессиональный Документы
Культура Документы
Вступление
В настоящее время отечественная криптография базируется на нескольких
основных государственных стандартах:
ГОСТ 34.10. Информационная технология. Криптографическая защита
информации. Процессы формирования и проверки электронной цифровой
подписи (действующая на сегодня редакция 2012 года);
ГОСТ 34.11. Информационная технология. Криптографическая защита
информации. Функция хэширования (действующая на сегодня редакция
2012 года);
ГОСТ 34.12. Информационная технология. Криптографическая защита
информации. Блочные шифры (действующая на сегодня редакция 2015
года);
ГОСТ 34.13. Информационная технология. Криптографическая защита
информации. Режимы работы блочных шифров (действующая на сегодня
редакция 2015 года).
2
Рисунок 2 - Схема работы алгоритма при зашифровании и при расшифровании
Итерационные (или раундовые) ключи получаются путем определенных
преобразований на основе мастер-ключа, длина которого, составляет 256 бит.
Этот процесс начинается с разбиения мастер-ключа пополам, так получается
первая пара раундовых ключей. Для генерации каждой последующей пары
раундовых ключей применяется восемь итераций сети Фейстеля, в каждой
итерации используется константа, которая вычисляется путем применения
линейного преобразования алгоритма к значению номера итерации.
3
Рисунок 3 - Схема получения итерационных (раундовых) ключей
Рисунок 3 - Преобразование S
5
5. Обратное нелинейное биективное преобразование (обратное
преобразование S):
Поскольку нам нужно не только зашифровывать сообщения, но и
расшифровывать тоже, то каждому преобразованию зашифрования необходимо
ставить в соответствие обратное преобразование для расшифрования. Сама
функция обратного S-преобразования выглядит практически так же, как и
прямое S-преобразование:
static void GOST_Kuz_reverse_S(const uint8_t *in_data, uint8_t *out_data)
{
int i;
for (i = 0; i < BLOCK_SIZE; i++)
out_data[i] = reverse_Pi[in_data[i]];
}
6
0xDB, 0x69, 0xB3, 0x14, 0x95, 0xBE, 0x62, 0xA1,
0x3B, 0x16, 0x66, 0xE9, 0x5C, 0x6C, 0x6D, 0xAD,
0x37, 0x61, 0x4B, 0xB9, 0xE3, 0xBA, 0xF1, 0xA0,
0x85, 0x83, 0xDA, 0x47, 0xC5, 0xB0, 0x33, 0xFA,
0x96, 0x6F, 0x6E, 0xC2, 0xF6, 0x50, 0xFF, 0x5D,
0xA9, 0x8E, 0x17, 0x1B, 0x97, 0x7D, 0xEC, 0x58,
0xF7, 0x1F, 0xFB, 0x7C, 0x09, 0x0D, 0x7A, 0x67,
0x45, 0x87, 0xDC, 0xE8, 0x4F, 0x1D, 0x4E, 0x04,
0xEB, 0xF8, 0xF3, 0x3E, 0x3D, 0xBD, 0x8A, 0x88,
0xDD, 0xCD, 0x0B, 0x13, 0x98, 0x02, 0x93, 0x80,
0x90, 0xD0, 0x24, 0x34, 0xCB, 0xED, 0xF4, 0xCE,
0x99, 0x10, 0x44, 0x40, 0x92, 0x3A, 0x01, 0x26,
0x12, 0x1A, 0x48, 0x68, 0xF5, 0x81, 0x8B, 0xC7,
0xD6, 0x20, 0x0A, 0x08, 0x00, 0x4C, 0xD7, 0x74
};
7
Далее, используя приведенную выше функцию, реализуем
преобразование R, которое является частью линейного преобразования L.
Преобразование R выполняется с использованием линейного регистра сдвига с
обратной связью. Каждый байт из блока умножается с помощью функции
GOST_Kuz_GF_Mul на один из коэффициентов из ряда (148, 32, 133, 16, 194, 192, 1,
251, 1, 192, 194, 16, 133, 32, 148, 1) в зависимости от порядкового номера байта.
Байты складываются между собой по модулю 2, и все 16 байт блока сдвигаются
в сторону младшего разряда, а полученное число записывается на место
считанного байта.
8
internal[15] = a_15;
memcpy(state, internal, BLOCK_SIZE);
}
9
for (i = 0; i < 16; i++)
{
internal[i] = state[i - 1];// Двигаем все на старые места
a_0 ^= GOST_Kuz_GF_mul(internal[i], l_vec[i]);
}
internal[0] = a_0;
memcpy(state, internal, BLOCK_SIZE);
}
8. Развертывание ключей:
В начале мы уже говорили, что для зашифрования и расшифрования нам
нужны десять итерационных ключей, а для их получения необходимы 32
итерационные константы, которые получаются из порядкового номера итерации
с помощью L-преобразования.
Для начала определим место для хранения этих итерационных констант:
vect iter_C[32];// Итерационные константы C
10
GOST_Kuz_S(internal, internal);
GOST_Kuz_L(internal, internal);
GOST_Kuz_X(internal, in_key_2, out_key_1);
}
11
GOST_Kuz_F(iter_3, iter_4, iter_1, iter_2, iter_C[3 + 8 * i]);
GOST_Kuz_F(iter_1, iter_2, iter_3, iter_4, iter_C[4 + 8 * i]);
GOST_Kuz_F(iter_3, iter_4, iter_1, iter_2, iter_C[5 + 8 * i]);
GOST_Kuz_F(iter_1, iter_2, iter_3, iter_4, iter_C[6 + 8 * i]);
GOST_Kuz_F(iter_3, iter_4, iter_1, iter_2, iter_C[7 + 8 * i]);
memcpy(iter_key[2 * i + 2], iter_1, 64);
memcpy(iter_key[2 * i + 3], iter_2, 64);
}
}
9. Шифрование
Шифрование производится путем девяти итераций, включающих в себя
преобразование X (сложение по модулю 2 исходного сообщения с очередным
итерационным ключом), преобразование S и преобразование L, а также
неполной десятой итерации, состоящей из преобразования X (сложение по
модулю 2 с последним итерационным ключом):
void GOST_Kuz_Encript(const uint8_t *blk, uint8_t *out_blk)
{
int i;
memcpy(out_blk, blk, BLOCK_SIZE);
10. Расшифрование
Расшифрование производится в обратном порядке и с использованием
обратных преобразований:
void GOST_Kuz_Decript(const uint8_t *blk, uint8_t *out_blk)
{
int i;
memcpy(out_blk, blk, BLOCK_SIZE);
13
Рисунок 5 - Расшифрованные и зашифрованные строки из примеров,
приведенных в стандарте
11.Заключение
Мы научились кузнечику
14