Открыть боковую панель
Моисеенко Андрей Алексеевич
CryptLib
Коммиты
af1df895
Коммит
af1df895
создал
Мар 10, 2025
по автору
Моисеенко Андрей Алексеевич
Просмотр файлов
~
владелец
f90bea17
Изменения
2
Скрыть пробелы
Построчно
Рядом
Kuznechik_MAA.cpp
Просмотр файла @
af1df895
...
...
@@ -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
]
=
Pi
2
[(
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
*
b
yte
=
(
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
*
b
yte
=
(
unsigned
char
*
)
in_out
;
unsigned
char
*
b
=
(
unsigned
char
*
)
in_out
;
for
(
int
i
=
14
;
i
>=
0
;
i
--
)
{
b
yte
[
i
+
1
]
=
b
yte
[
i
];
acc
^=
GF_mult
(
b
yte
[
i
],
linear_vector
[
i
]);
b
[
i
+
1
]
=
b
[
i
];
acc
^=
GF_mult
(
b
[
i
],
linear_vector
[
i
]);
}
b
yte
[
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
*
b
yte
=
(
unsigned
char
*
)
in_out
;
unsigned
char
*
b
=
(
unsigned
char
*
)
in_out
;
for
(
int
i
=
0
;
i
<
15
;
i
++
)
{
b
yte
[
i
]
=
b
yte
[
i
+
1
];
acc
^=
GF_mult
(
b
yte
[
i
],
linear_vector
[
i
]);
b
[
i
]
=
b
[
i
+
1
];
acc
^=
GF_mult
(
b
[
i
],
linear_vector
[
i
]);
}
b
yte
[
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
]
=
((
c
hunk
*
)
key
)[
0
]
[
0
]
;
round_keys
[
0
][
1
]
=
ks
[
0
][
1
]
=
((
c
hunk
*
)
key
)[
0
][
1
];
round_keys
[
1
][
0
]
=
ks
[
1
][
0
]
=
((
c
hunk
*
)
key
)[
1
][
0
];
round_keys
[
1
][
1
]
=
ks
[
1
][
1
]
=
((
c
hunk
*
)
key
)[
1
][
1
];
round_keys
[
0
][
0
]
=
ks
[
0
][
0
]
=
((
c
onst
_uqword
*
)
key
)[
0
];
round_keys
[
0
][
1
]
=
ks
[
0
][
1
]
=
((
c
onst
_uqword
*
)
key
)[
1
];
round_keys
[
1
][
0
]
=
ks
[
1
][
0
]
=
((
c
onst
_uqword
*
)
key
)[
2
];
round_keys
[
1
][
1
]
=
ks
[
1
][
1
]
=
((
c
onst
_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
);
...
...
Kuznechik_MAA.h
Просмотр файла @
af1df895
...
...
@@ -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.
Сначала завершите редактирование этого сообщения!
Отмена
Пожалуйста,
зарегистрируйтесь
или
войдите
чтобы прокомментировать