Коммит af1df895 создал по автору Моисеенко Андрей Алексеевич's avatar Моисеенко Андрей Алексеевич
Просмотр файлов

~

владелец f90bea17
......@@ -101,7 +101,9 @@ const unsigned char CChipherKuznechik::Pi[256] =
};
// Таблица обратного нелинейного преобразования
const unsigned char CChipherKuznechik::Pi_reverse[256] =
//const
unsigned char CChipherKuznechik::Pi_reverse[256] = {};
/*
{
0xA5, 0x2D, 0x32, 0x8F, 0x0E, 0x30, 0x38, 0xC0, 0x54, 0xE6, 0x9E, 0x39, 0x55, 0x7E, 0x52, 0x91,
0x64, 0x03, 0x57, 0x5A, 0x1C, 0x60, 0x07, 0x18, 0x21, 0x72, 0xA8, 0xD1, 0x29, 0xC6, 0xA4, 0x3F,
......@@ -120,6 +122,10 @@ const unsigned char CChipherKuznechik::Pi_reverse[256] =
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
};
*/
unsigned short * CChipherKuznechik::Pi2 = nullptr;
unsigned short * CChipherKuznechik::Pi2_reverse = nullptr;
// Вектор линейного преобразования
const unsigned char CChipherKuznechik::linear_vector[16] =
......@@ -138,34 +144,151 @@ const unsigned char CChipherKuznechik::StaticKey[32] =
CChipherKuznechik::CChipherKuznechik() noexcept
{
memset(round_keys, 0, sizeof(round_keys));
};
#ifdef KUZNECHIK_DEBUG
printf("%d %d\n", (int)sizeof(round_keys), 20 * (int)sizeof(_uqword));
#endif
ClearRoundKeys();
CreateTables();
}
CChipherKuznechik::~CChipherKuznechik()
{
memset(round_keys, 0, sizeof(round_keys));
};
ClearRoundKeys();
}
void CChipherKuznechik::ClearRoundKeys() noexcept
{
for (int i = 0; i < 10; i++)
{
round_keys[i].Zero();
}
}
void CChipherKuznechik::CreateTables() noexcept
{
if (!Pi_reverse[0xff])
{
for (int i = 0; i < 0x100; i++)
{
Pi_reverse[Pi[i]] = i;
}
int j = 0;
for (int i = 0; i < 0x100; i++)
{
if (!Pi_reverse[i])
{
j++;
}
}
if (j != 1)
{
//printf("j = %d\n", j);
exit(102);
}
}
if (!Pi2)
{
unsigned short * p = new unsigned short[0x10000];
if (!p)
{
exit(102);
}
memset(p, 0, 0x10000 * sizeof(unsigned short));
Pi2 = p;
}
if (!Pi2_reverse)
{
unsigned short * p = new unsigned short[0x10000];
if (!p)
{
exit(102);
}
memset(p, 0, 0x10000 * sizeof(unsigned short));
Pi2_reverse = p;
}
if (!Pi2[0xffff])
{
for (int i = 0; i < 0x10000; i++)
{
#ifdef TOOLSLIB_LITTLE_ENDIAN
Pi2[i] = (unsigned short)((((unsigned short)Pi[i >> 8]) << 8) | Pi[i & 0xff]);
#else
Pi2[i] = (unsigned short)(((unsigned short)Pi[i & 0xff] << 8) | Pi[i >> 8]);
#endif
}
}
if (!Pi2_reverse[0xffff])
{
for (int i = 0; i < 0x10000; i++)
{
#ifdef TOOLSLIB_LITTLE_ENDIAN
Pi2_reverse[i] = (unsigned short)((((unsigned short)Pi_reverse[i >> 8]) << 8) | Pi_reverse[i & 0xff]);
#else
Pi2_reverse[i] = (unsigned short)(((unsigned short)Pi_reverse[i & 0xff] << 8) | Pi_reverse[i >> 8]);
#endif
}
}
}
// Функция S
void CChipherKuznechik::S(_uqword* in_out) noexcept
{
#if 0
// Переход к представлению в байтах
unsigned char *b = (unsigned char*)in_out;
for (int i = 0; i < KUZNECHIK_BLOCK_SIZE; i++)
{
b[i] = Pi[b[i]];
}
#else
// Переход к представлению в байтах
unsigned char *byte = (unsigned char*)in_out;
for (int i = 0; i < KUZNECHIK_BLOCK_SIZE; i++)
unsigned short *w = (unsigned short*)in_out;
for (int i = 0; i < KUZNECHIK_BLOCK_SIZE / 2; i++)
{
byte[i] = Pi[byte[i]];
w[i] = Pi2[(unsigned)w[i]];
}
#endif
}
//#define tst1 // // g++ (Debian 12.2.0-14) 12.2.0 -O3 not -lto have a bug if tst1 not defined and print_chunk(***) is not exists in the tail
// Обратная функция S
void CChipherKuznechik::S_reverse(_uqword* in_out) noexcept
{
#if 0
// Переход к представлению в байтах
unsigned char *byte = (unsigned char*)in_out;
for (int i = 0; i < KUZNECHIK_BLOCK_SIZE; i++)
unsigned char *b = (unsigned char*)in_out;
for (int i = 0; i < KUZNECHIK_BLOCK_SIZE; i++)
{
byte[i] = Pi_reverse[byte[i]];
b[i] = Pi_reverse[b[i]];
}
#else
#ifdef tst1
// Переход к представлению в байтах
unsigned char b16[KUZNECHIK_BLOCK_SIZE];
unsigned char *b = (unsigned char*)in_out;
for (int i = 0; i < KUZNECHIK_BLOCK_SIZE; i++)
{
b16[i] = Pi_reverse[b[i]];
}
#endif
// Переход к представлению в байтах
unsigned short *w = (unsigned short*)in_out;
for (int i = 0; i < KUZNECHIK_BLOCK_SIZE / 2; i++)
{
#ifdef tst1
unsigned short ww = w[i];
#endif
w[i] = Pi2_reverse[(unsigned)w[i]];
#ifdef tst1
if (((unsigned short*)b16)[i] != w[i])
{
printf("[%04x] = %04x , != %04x\n", ww, w[i], ((unsigned short*)b16)[i]);
}
#endif
}
#endif
//print_chunk(b16);
//print_chunk(in_out);
}
// Функция умножения в поле Галуа
......@@ -192,13 +315,13 @@ void CChipherKuznechik::R(unsigned char *in_out) noexcept
// Аккумулятор
unsigned char acc = in_out[15];
// Переход к представлению в байтах
unsigned char *byte = (unsigned char*)in_out;
unsigned char *b = (unsigned char*)in_out;
for (int i = 14; i >= 0; i--)
{
byte[i + 1] = byte[i];
acc ^= GF_mult(byte[i], linear_vector[i]);
b[i + 1] = b[i];
acc ^= GF_mult(b[i], linear_vector[i]);
}
byte[0] = acc;
b[0] = acc;
}
// Обратная функция R
......@@ -207,15 +330,15 @@ void CChipherKuznechik::R_reverse(unsigned char *in_out) noexcept
// Аккумулятор
unsigned char acc = in_out[0];
// Переход к представлению в байтах
unsigned char *byte = (unsigned char*)in_out;
unsigned char *b = (unsigned char*)in_out;
for (int i = 0; i < 15; i++)
{
byte[i] = byte[i + 1];
acc ^= GF_mult(byte[i], linear_vector[i]);
b[i] = b[i + 1];
acc ^= GF_mult(b[i], linear_vector[i]);
}
byte[15] = acc;
b[15] = acc;
}
// Функция L
......@@ -230,10 +353,10 @@ void CChipherKuznechik::L(unsigned char* in_out) noexcept
// Обратная функция L
void CChipherKuznechik::L_reverse(unsigned char *in_out) noexcept
{
for (int i = 0; i < 16; i++)
for (int i = 0; i < KUZNECHIK_BLOCK_SIZE; i++)
{
R_reverse(in_out);
}
}
}
// Генерация итерационных ключей
......@@ -253,19 +376,19 @@ void CChipherKuznechik::gen_round_keys(const unsigned char* key, chunk* round_ke
}
// Итерационные ключи (четный и нечетный)
chunk ks[2] = {};
chunk ks[2] = {false, false};
// Разместим ключ шифрования
// результат = итерационный ключ = (преобразование к указателю на чанк)[номер чанка][часть чанка]
round_keys[0][0] = ks[0][0] = ((chunk*)key)[0][0];
round_keys[0][1] = ks[0][1] = ((chunk*)key)[0][1];
round_keys[1][0] = ks[1][0] = ((chunk*)key)[1][0];
round_keys[1][1] = ks[1][1] = ((chunk*)key)[1][1];
round_keys[0][0] = ks[0][0] = ((const _uqword*)key)[0];
round_keys[0][1] = ks[0][1] = ((const _uqword*)key)[1];
round_keys[1][0] = ks[1][0] = ((const _uqword*)key)[2];
round_keys[1][1] = ks[1][1] = ((const _uqword*)key)[3];
// Генерация оставшихся ключей с использованием констант
for (i = 1; i <= 32; i++)
{
// Новый ключ
chunk new_key = {0};
chunk new_key = {false};
// Преобразование X
X(ks[0], (const _uqword*)cs[i - 1], new_key);
......@@ -277,21 +400,15 @@ void CChipherKuznechik::gen_round_keys(const unsigned char* key, chunk* round_ke
X(new_key, ks[1], new_key);
// Сдвигаем ключи
ks[1][0] = ks[0][0];
ks[1][1] = ks[0][1];
ks[1] = ks[0];
// Записываем новый ключ
ks[0][0] = new_key[0];
ks[0][1] = new_key[1];
ks[0] = new_key;
// Каждую 8 итерацию сети Фейстеля за исключением нулевой запишем ключи
if ((i > 0) && (i % 8 == 0))
{
round_keys[(i >> 2)][0] = ks[0][0];
round_keys[(i >> 2)][1] = ks[0][1];
round_keys[(i >> 2) + 1][0] = ks[1][0];
round_keys[(i >> 2) + 1][1] = ks[1][1];
round_keys[(i >> 2)] = ks[0];
round_keys[(i >> 2) + 1] = ks[1];
}
}
}
......@@ -301,19 +418,17 @@ void CChipherKuznechik::gen_round_keys(const unsigned char* key, chunk* round_ke
void CChipherKuznechik::kuznechik_encrypt128(const chunk* round_keys, _uqword* p) noexcept
{
// В течении 10 итераций
for (int i = 0; i < 10; i++)
for (int i = 0; i <= 8; i++)
{
// Преобразование X
X(p, round_keys[i], p);
// Для всех итераций кроме последней
if (i < 9)
{
// Преобразование S
S(p);
// Преобразование L
L((unsigned char*)p);
}
// Преобразование S
S(p);
// Преобразование L
L((unsigned char*)p);
}
// Преобразование X
X(p, round_keys[9], p);
}
void CChipherKuznechik::kuznechik_decrypt128(const chunk* round_keys, _uqword* p) noexcept
......@@ -336,7 +451,7 @@ void CChipherKuznechik::kuznechik_decrypt128(const chunk* round_keys, _uqword* p
void CChipherKuznechik::kuznechik_encrypt(const chunk* round_keys, const _uqword* in, _uqword* out) noexcept
{
// Буфер
chunk p;
_uqword p[2];
// Создадим копию входных данных
p[0] = in[0]; //memcpy(p, in, sizeof(chunk));
p[1] = in[1];
......@@ -351,7 +466,7 @@ void CChipherKuznechik::kuznechik_encrypt(const chunk* round_keys, const _uqword
void CChipherKuznechik::kuznechik_decrypt(const chunk* round_keys, const _uqword* in, _uqword* out) noexcept
{
// Буфер
chunk p;
_uqword p[2];
// Создадим копию входных данных
p[0] = in[0]; //memcpy(p, in, sizeof(chunk));
p[1] = in[1];
......@@ -366,7 +481,7 @@ void CChipherKuznechik::kuznechik_decrypt(const chunk* round_keys, const _uqword
// Печать чанка
void CChipherKuznechik::print_chunk(const void* p) noexcept
{
for (int i = 0; i < (int)sizeof(chunk); i++)
for (int i = 0; i < KUZNECHIK_BLOCK_SIZE; i++)
{
printf("0x%02X ", ((unsigned char*)p)[i]);
}
......@@ -380,9 +495,9 @@ void CChipherKuznechik::SetKey(const unsigned char* key) noexcept
#ifdef KUZNECHIK_DEBUG
// Вывод итерационных ключей
printf("Итерацционные ключи:\n");
printf("Итерационные ключи:\n");
for (int i = 0; i < 10; i++)
print_chunk(round_keys[i]);
print_chunk((const unsigned char*)round_keys[i]);
#endif
}
......@@ -466,10 +581,10 @@ int main_kuznechik(int argc, char *argv[])
};
// Открытые данные
const unsigned char data[KUZNECHIK_BLOCK_SIZE] =
{
unsigned char data[KUZNECHIK_BLOCK_SIZE] =
{
0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,
0xff,0xee,0xdd,0xcc,0xbb,0xaa,0x99,0x88
0xff,0xee,0xdd,0xcc,0xbb,0xaa,0x99,0x88
};
const unsigned char edata[KUZNECHIK_BLOCK_SIZE] =
......@@ -478,6 +593,22 @@ int main_kuznechik(int argc, char *argv[])
0x5A,0x46,0x8D,0x42,0xB9,0xD4,0xED,0xCD
};
/*
CMaaFile f("kuzn_gcc_workaround.tmp", CMaaFile::eRWC, false); // g++ (Debian 12.2.0-14) 12.2.0 -O3 not -lto workaround
f.Write(data, (int)sizeof(data));
f.Seek(0);
f.Read(data, (int)sizeof(data));
f.Close();
*/
/*
const unsigned char Sdata[KUZNECHIK_BLOCK_SIZE] =
{
0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,
0xff,0xee,0xdd,0xcc,0xbb,0xaa,0x99,0x88
};
*/
// Вывод открытых данных
printf("Ключ:\n");
CChipherKuznechik::print_chunk(&key[0]);
......@@ -489,6 +620,12 @@ int main_kuznechik(int argc, char *argv[])
CChipherKuznechik k;
k.SetKey(key);
/*
printf("S_reverse-данные:\n");
CChipherKuznechik::S_reverse((_uqword*)Sdata);
CChipherKuznechik::print_chunk(Sdata);
*/
/*
Итерационные ключи:
0x88 0x99 0xAA 0xBB 0xCC 0xDD 0xEE 0xFF 0x00 0x11 0x22 0x33 0x44 0x55 0x66 0x77
......@@ -504,16 +641,16 @@ int main_kuznechik(int argc, char *argv[])
*/
// Зашифрованные данные
CChipherKuznechik::chunk encrypted;
k.Encrypt(data, sizeof(data), (unsigned char*)encrypted);
unsigned char encrypted[KUZNECHIK_BLOCK_SIZE] = {};
k.Encrypt(data, sizeof(data), encrypted);
printf("Зашифрованные данные:\n");
CChipherKuznechik::print_chunk(encrypted);
printf("%s\n", !memcmp(encrypted, edata, sizeof(edata)) ? "== (ok)" : "!= (fail)");
// Результат расшифровки
CChipherKuznechik::chunk decrypted;
k.Decrypt((const unsigned char*)encrypted, sizeof(data), (unsigned char*)decrypted);
unsigned char decrypted[KUZNECHIK_BLOCK_SIZE] = {};
k.Decrypt((const unsigned char*)encrypted, sizeof(encrypted), decrypted);
printf("Расшифрованные данные:\n");
CChipherKuznechik::print_chunk(decrypted);
......
......@@ -85,14 +85,56 @@ class CChipherKuznechik
{
public:
// Один блок (чанк) задается как массив двух беззнаковых целых по 64 бита
typedef _uqword chunk[2];
struct chunk
{
_uqword m[2];
chunk() noexcept {}
chunk(bool b) noexcept : m{} {}
_uqword& operator[](int idx) noexcept
{
return m[idx];
}
const _uqword& operator[](int idx) const noexcept
{
return m[idx];
}
chunk& operator=(const chunk& That) noexcept
{
m[0] = That.m[0];
m[1] = That.m[1];
return *this;
}
operator _uqword* () noexcept
{
return m;
}
operator const _uqword* () const noexcept
{
return m;
}
operator unsigned char* () noexcept
{
return (unsigned char*)m;
}
operator const unsigned char* () const noexcept
{
return (const unsigned char*)m;
}
void Zero() noexcept
{
m[1] = m[0] = 0;
}
};
protected:
//public:
// Итерационные ключи
chunk round_keys[10];
// Таблица прямого нелинейного преобразования согластно ГОСТ 34.12-2015
static const unsigned char Pi[256], Pi_reverse[256];
static const unsigned char Pi[256];//, Pi_reverse[256];
static unsigned char Pi_reverse[256];
static unsigned short *Pi2, *Pi2_reverse;
static const unsigned char linear_vector[16];
static const unsigned char StaticKey[32];
......@@ -114,6 +156,8 @@ protected:
static void kuznechik_decrypt(const chunk* round_keys, const _uqword* in, _uqword* out) noexcept;
static void kuznechik_encrypt128(const chunk* round_keys, _uqword* p) noexcept;
static void kuznechik_decrypt128(const chunk* round_keys, _uqword* p) noexcept;
void ClearRoundKeys() noexcept;
static void CreateTables() noexcept;
public:
static void print_chunk(const void* p) noexcept;
CChipherKuznechik() noexcept;
......
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать