Commit 168223cd authored by Романов Никита Сергеевич's avatar Романов Никита Сергеевич
Browse files

ADD: belt block cipher and tests from STB

No related merge requests found
Showing with 379 additions and 0 deletions
+379 -0
......@@ -95,6 +95,7 @@ set( AKRYPT_SOURCES
source/ak_blom.c
source/ak_kdf.c
source/ak_encrypt.c
source/ak_belt.c
)
# -------------------------------------------------------------------------------------------------- #
......
/* --------------------------------------------------------------------------------- */
/* Контрольный пример расшифрования одного блока из стандарта (STB 34.101.31-2020) */
/* --------------------------------------------------------------------------------- */
#include <stdio.h>
#include <libakrypt.h>
int main( void )
{
/* код ошибки, возвращаемый функциями библиотеки */
int error = ak_error_ok;
/* статус выполнения программы */
int exitstatus = EXIT_FAILURE;
/* входной блок (уже зашифрован)*/
ak_uint8 indec[16] =
{
0xE1,0x2B,0xDC,0x1A,
0xE2,0x82,0x57,0xEC,
0x70,0x3F,0xCC,0xF0,
0x95,0xEE,0x8D,0xF1
};
/* расшифрованный блок */
ak_uint8 out[16] = {0};
/* константное значение ключа */
ak_uint8 keydec[32] =
{
0x92,0xBD,0x9B,0x1C,
0xE5,0xD1,0x41,0x01,
0x54,0x45,0xFB,0xC9,
0x5E,0x4D,0x0E,0xF2,
0x68,0x20,0x80,0xAA,
0x22,0x7D,0x64,0x2F,
0x26,0x87,0xF9,0x34,
0x90,0x40,0x55,0x11
};
/* инициализируем библиотеку */
if( ak_libakrypt_create( NULL ) != ak_true ) {
ak_libakrypt_destroy();
return EXIT_FAILURE;
}
/* контекст алгоритма блочного шифрования */
struct bckey ctx;
/* выполняем последовательный вызов двух функций:
создаем ключ алгоритма Belt и присваиваем ему константное значение */
ak_bckey_create_belt( &ctx );
ak_bckey_set_key( &ctx, keydec, 32 );
size_t i;
// расшифровываем в режиме простой замены один блок
if(( ak_bckey_decrypt_ecb( &ctx, indec, out, 16 ))
!= ak_error_ok ) goto exlab;
printf("Decryption:\n");
printf("m: ");
for (i = 0; i < 16; ++i) { printf("%02X ", indec[i]); }
printf("\nk: ");
for (i = 0; i < 32; ++i) { printf("%02X ", keydec[i]); }
printf("\nc: ");
for (i = 0; i < 16; ++i) { printf("%02X ", out[i]); }
printf("\n");
printf("Expected:\n");
printf("c: 0D C5 30 06 00 CA B8 40 B3 84 48 E5 E9 93 F4 21\n");
/* после использования необходимо удалить контекст секретного ключа */
exlab: ak_bckey_destroy( &ctx );
/* завершаем работу */
if( error == ak_error_ok ) exitstatus = EXIT_SUCCESS;
ak_libakrypt_destroy();
return exitstatus;
}
/* --------------------------------------------------------------------------------- */
/* Контрольный пример зашифрования одного блока из стандарта (STB 34.101.31-2020) */
/* --------------------------------------------------------------------------------- */
#include <stdio.h>
#include <libakrypt.h>
int main( void )
{
/* код ошибки, возвращаемый функциями библиотеки */
int error = ak_error_ok;
/* статус выполнения программы */
int exitstatus = EXIT_FAILURE;
/* входной блок */
ak_uint8 inenc[16] =
{
0xB1,0x94,0xBA,0xC8,
0x0A,0x08,0xF5,0x3B,
0x36,0x6D,0x00,0x8E,
0x58,0x4A,0x5D,0xE4,
};
/* выходной блок после зашифрования */
ak_uint8 outenc[16] = {0};
/* расшифрованный блок */
ak_uint8 outdec[16] = {0};
/* константное значение ключа */
ak_uint8 key[32] = {
0xE9,0xDE,0xE7,0x2C,
0x8F,0x0C,0x0F,0xA6,
0x2D,0xDB,0x49,0xF4,
0x6F,0x73,0x96,0x47,
0x06,0x07,0x53,0x16,
0xED,0x24,0x7A,0x37,
0x39,0xCB,0xA3,0x83,
0x03,0xA9,0x8B,0xF6,
};
/* инициализируем библиотеку */
if( ak_libakrypt_create( NULL ) != ak_true ) {
ak_libakrypt_destroy();
return EXIT_FAILURE;
}
/* контекст алгоритма блочного шифрования */
struct bckey ctx;
/* выполняем последовательный вызов двух функций:
создаем ключ алгоритма Belt и присваиваем ему константное значение */
ak_bckey_create_belt( &ctx );
ak_bckey_set_key( &ctx, key, 32 );
size_t i;
// зашифровываем в режиме простой замены один блок
if(( ak_bckey_encrypt_ecb( &ctx, inenc, outenc, 16 ))
!= ak_error_ok ) goto exlab;
printf("Encryption:\n");
printf("m: ");
for (i = 0; i < 16; ++i) { printf("%02X ", inenc[i]); }
printf("\nk: ");
for (i = 0; i < 32; ++i) { printf("%02X ", key[i]); }
printf("\nc: ");
for (i = 0; i < 16; ++i) { printf("%02X ", outenc[i]); }
printf("\n");
printf("Expected:\n");
printf("c: 69 CC A1 C9 35 57 C9 E3 D6 6B C3 E0 FA 88 FA 6E\n");
/* после использования необходимо удалить контекст секретного ключа */
exlab: ak_bckey_destroy( &ctx );
/* завершаем работу */
if( error == ak_error_ok ) exitstatus = EXIT_SUCCESS;
ak_libakrypt_destroy();
return exitstatus;
}
/* ----------------------------------------------------------------------------------------------- */
/* */
/* Реализация зашифрования и расшифрования одного блока шифром */
/* из Белорусского стандарта STB 34.101.31-2020 */
/* */
/* ----------------------------------------------------------------------------------------------- */
#include <libakrypt-internal.h>
#define ROTL32(x, r) (((x) << (r)) | ((x) >> (32 - (r))))
#define HU1(x,H) ((ak_uint32) ((H)[ (((x) >> 24) & 0xff) ]) << 24 )
#define HU2(x,H) ((ak_uint32) ((H)[ (((x) >> 16) & 0xff) ]) << 16 )
#define HU3(x,H) ((ak_uint32) ((H)[ (((x) >> 8) & 0xff) ]) << 8 )
#define HU4(x,H) ((ak_uint32) ((H)[ (((x) >> 0) & 0xff) ]) << 0 )
#define G(x,H,r) ROTL32(HU4((x),(H)) | HU3((x),(H)) | HU2((x),(H)) | HU1((x),(H)),(r))
#define SWAP(x,y,tmp) (tmp) = (x); (x) = (y); (y) = (tmp);
static ak_uint32 load32(const void *in)
{
const ak_uint8 *p = (const ak_uint8 *)in;
return ((ak_uint32)p[0] << 0) |
((ak_uint32)p[1] << 8) |
((ak_uint32)p[2] << 16) |
((ak_uint32)p[3] << 24);
}
static void store32(void *out, const ak_uint32 v)
{
ak_uint8 *p = (ak_uint8 *)out;
p[0] = (ak_uint8)(v >> 0);
p[1] = (ak_uint8)(v >> 8);
p[2] = (ak_uint8)(v >> 16);
p[3] = (ak_uint8)(v >> 24);
}
static const ak_uint8 H[256] =
{
0xB1, 0x94, 0xBA, 0xC8, 0x0A, 0x08, 0xF5, 0x3B, 0x36, 0x6D, 0x00, 0x8E, 0x58, 0x4A, 0x5D, 0xE4,
0x85, 0x04, 0xFA, 0x9D, 0x1B, 0xB6, 0xC7, 0xAC, 0x25, 0x2E, 0x72, 0xC2, 0x02, 0xFD, 0xCE, 0x0D,
0x5B, 0xE3, 0xD6, 0x12, 0x17, 0xB9, 0x61, 0x81, 0xFE, 0x67, 0x86, 0xAD, 0x71, 0x6B, 0x89, 0x0B,
0x5C, 0xB0, 0xC0, 0xFF, 0x33, 0xC3, 0x56, 0xB8, 0x35, 0xC4, 0x05, 0xAE, 0xD8, 0xE0, 0x7F, 0x99,
0xE1, 0x2B, 0xDC, 0x1A, 0xE2, 0x82, 0x57, 0xEC, 0x70, 0x3F, 0xCC, 0xF0, 0x95, 0xEE, 0x8D, 0xF1,
0xC1, 0xAB, 0x76, 0x38, 0x9F, 0xE6, 0x78, 0xCA, 0xF7, 0xC6, 0xF8, 0x60, 0xD5, 0xBB, 0x9C, 0x4F,
0xF3, 0x3C, 0x65, 0x7B, 0x63, 0x7C, 0x30, 0x6A, 0xDD, 0x4E, 0xA7, 0x79, 0x9E, 0xB2, 0x3D, 0x31,
0x3E, 0x98, 0xB5, 0x6E, 0x27, 0xD3, 0xBC, 0xCF, 0x59, 0x1E, 0x18, 0x1F, 0x4C, 0x5A, 0xB7, 0x93,
0xE9, 0xDE, 0xE7, 0x2C, 0x8F, 0x0C, 0x0F, 0xA6, 0x2D, 0xDB, 0x49, 0xF4, 0x6F, 0x73, 0x96, 0x47,
0x06, 0x07, 0x53, 0x16, 0xED, 0x24, 0x7A, 0x37, 0x39, 0xCB, 0xA3, 0x83, 0x03, 0xA9, 0x8B, 0xF6,
0x92, 0xBD, 0x9B, 0x1C, 0xE5, 0xD1, 0x41, 0x01, 0x54, 0x45, 0xFB, 0xC9, 0x5E, 0x4D, 0x0E, 0xF2,
0x68, 0x20, 0x80, 0xAA, 0x22, 0x7D, 0x64, 0x2F, 0x26, 0x87, 0xF9, 0x34, 0x90, 0x40, 0x55, 0x11,
0xBE, 0x32, 0x97, 0x13, 0x43, 0xFC, 0x9A, 0x48, 0xA0, 0x2A, 0x88, 0x5F, 0x19, 0x4B, 0x09, 0xA1,
0x7E, 0xCD, 0xA4, 0xD0, 0x15, 0x44, 0xAF, 0x8C, 0xA5, 0x84, 0x50, 0xBF, 0x66, 0xD2, 0xE8, 0x8A,
0xA2, 0xD7, 0x46, 0x52, 0x42, 0xA8, 0xDF, 0xB3, 0x69, 0x74, 0xC5, 0x51, 0xEB, 0x23, 0x29, 0x21,
0xD4, 0xEF, 0xD9, 0xB4, 0x3A, 0x62, 0x28, 0x75, 0x91, 0x14, 0x10, 0xEA, 0x77, 0x6C, 0xDA, 0x1D
};
static const size_t KeyIndex[8][7] =
{
{ 0, 1, 2, 3, 4, 5, 6 },
{ 7, 0, 1, 2, 3, 4, 5 },
{ 6, 7, 0, 1, 2, 3, 4 },
{ 5, 6, 7, 0, 1, 2, 3 },
{ 4, 5, 6, 7, 0, 1, 2 },
{ 3, 4, 5, 6, 7, 0, 1 },
{ 2, 3, 4, 5, 6, 7, 0 },
{ 1, 2, 3, 4, 5, 6, 7 }
};
/* ----------------------------------------------------------------------------------------------- */
/*! \brief Функция зашифрования одного блока информации алгоритмом блочного шифрования
* Belt (STB 34.101.31-2020).
@param skey Контекст секретного ключа.
@param input Блок входной информации (открытый текст).
@param output Блок выходной информации (шифртекст). */
/* ----------------------------------------------------------------------------------------------- */
static void ak_belt_encrypt( ak_skey skey, ak_pointer input, ak_pointer output )
{
// Преобразование входных и выходных указателей в массивы данных
const ak_uint8 *in = (const ak_uint8 *)input;
ak_uint8 *out = (ak_uint8 *)output;
ak_uint32 a = load32(in + 0);
ak_uint32 b = load32(in + 4);
ak_uint32 c = load32(in + 8);
ak_uint32 d = load32(in + 12);
ak_uint32 e;
size_t i;
ak_uint32 tmp;
ak_uint32 key[8] = {0};
ak_uint32 msk[8] = {0};
for (i = 0; i < 8; ++i)
{
key[i] = load32(skey->key + (4*i));
msk[i] = load32(skey->key + skey->key_size + (4*i));
}
for (i = 0; i < 8; ++i)
{
b ^= G((a + (key[KeyIndex[i][0]] ^ msk[KeyIndex[i][0]])),H,5);
c ^= G((d + (key[KeyIndex[i][1]] ^ msk[KeyIndex[i][1]])),H,21);
a -= G((b + (key[KeyIndex[i][2]] ^ msk[KeyIndex[i][2]])),H,13);
e = (G((b + c + (key[KeyIndex[i][3]] ^ msk[KeyIndex[i][3]])),H,21) ^ (ak_uint32)(i + 1));
b += e;
c -= e;
d += G((c + (key[KeyIndex[i][4]] ^ msk[KeyIndex[i][4]])),H,13);
b ^= G((a + (key[KeyIndex[i][5]] ^ msk[KeyIndex[i][5]])),H,21);
c ^= G((d + (key[KeyIndex[i][6]] ^ msk[KeyIndex[i][6]])),H,5);
SWAP(a, b, tmp);
SWAP(c, d, tmp);
SWAP(b, c, tmp);
}
store32(out + 0, b);
store32(out + 4, d);
store32(out + 8, a);
store32(out + 12, c);
}
/* ----------------------------------------------------------------------------------------------- */
/*! \brief Функция расшифрования одного блока информации алгоритмом Belt (STB 34.101.31-2020).
@param skey Контекст секретного ключа.
@param input Блок входной информации (шифртекст).
@param output Блок выходной информации (открытый текст). */
/* ----------------------------------------------------------------------------------------------- */
static void ak_belt_decrypt( ak_skey skey, ak_pointer input, ak_pointer output )
{
// Преобразование входных и выходных указателей в массивы данных
const ak_uint8 *in = (const ak_uint8 *)input;
ak_uint8 *out = (ak_uint8 *)output;
ak_uint32 a = load32(in + 0);
ak_uint32 b = load32(in + 4);
ak_uint32 c = load32(in + 8);
ak_uint32 d = load32(in + 12);
ak_uint32 e;
size_t i;
ak_uint32 tmp;
ak_uint32 key[8] = {0};
ak_uint32 msk[8] = {0};
for (i = 0; i < 8; ++i)
{
key[i] = load32(skey->key + (4*i));
msk[i] = load32(skey->key + skey->key_size + (4*i));
}
for (i = 0; i < 8; ++i)
{
b ^= G((a + (key[KeyIndex[7 - i][6]] ^ msk[KeyIndex[7 - i][6]])), H, 5);
c ^= G((d + (key[KeyIndex[7 - i][5]] ^ msk[KeyIndex[7 - i][5]])), H, 21);
a -= G((b + (key[KeyIndex[7 - i][4]] ^ msk[KeyIndex[7 - i][4]])), H, 13);
e = (G((b + c + (key[KeyIndex[7 - i][3]] ^ msk[KeyIndex[7 - i][3]])), H, 21) ^ (ak_uint32)(7 - i + 1));
b += e;
c -= e;
d += G((c + (key[KeyIndex[7 - i][2]] ^ msk[KeyIndex[7 - i][2]])), H, 13);
b ^= G((a + (key[KeyIndex[7 - i][1]] ^ msk[KeyIndex[7 - i][1]])), H, 21);
c ^= G((d + (key[KeyIndex[7 - i][0]] ^ msk[KeyIndex[7 - i][0]])), H, 5);
SWAP(a, b, tmp);
SWAP(c, d, tmp);
SWAP(a, d, tmp);
}
store32(out + 0, c);
store32(out + 4, a);
store32(out + 8, d);
store32(out + 12, b);
}
/* ----------------------------------------------------------------------------------------------- */
/*! Функция инициализирует контекст ключа алгоритма блочного шифрования Belt (STB 34.101.31-2020).
После инициализации устанавливаются обработчики (функции класса). Однако само значение
ключу не присваивается - поле `bkey->key` остается неопределенным.
@param bkey Контекст секретного ключа алгоритма блочного шифрования.
@return Функция возвращает код ошибки. В случаее успеха возвращается \ref ak_error_ok. */
/* ----------------------------------------------------------------------------------------------- */
int ak_bckey_create_belt( ak_bckey bkey )
{
int error = ak_error_ok;
if( bkey == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
"using null pointer to block cipher key context" );
/* создаем ключ алгоритма шифрования и определяем его методы */
if(( error = ak_bckey_create( bkey, 32, 16 )) != ak_error_ok )
return ak_error_message( error, __func__, "wrong initalization of block cipher key context" );
/* устанавливаем OID алгоритма шифрования */
if(( bkey->key.oid = ak_oid_find_by_name( "belt" )) == NULL ) {
error = ak_error_get_value();
ak_error_message( error, __func__, "wrong search of predefined belt block cipher OID" );
ak_bckey_destroy( bkey );
return error;
}
/* устанавливаем методы наложения маски и подсчёта контрольной суммы */
bkey->key.set_mask = ak_skey_set_mask_xor;
bkey->key.unmask = ak_skey_unmask_xor;
bkey->key.set_icode = ak_skey_set_icode_xor;
bkey->key.check_icode = ak_skey_check_icode_xor;
/* устанавливам методы зашифрования и расшифрования */
bkey->encrypt = ak_belt_encrypt;
bkey->decrypt = ak_belt_decrypt;
return error;
}
......@@ -82,6 +82,8 @@
static const char *asn1_magma_i[] = { "1.2.643.7.1.1.5.1", NULL };
static const char *asn1_kuznechik_n[] = { "kuznechik", "kuznyechik", "grasshopper", NULL };
static const char *asn1_kuznechik_i[] = { "1.2.643.7.1.1.5.2", NULL };
static const char *asn1_belt_n[] = { "belt", NULL };
static const char *asn1_belt_i[] = { "1.2.112.0.2.0.34.101.31.81", NULL };
static const char *asn1_ctr_magma_n[] = { "ctr-magma", NULL };
static const char *asn1_ctr_magma_i[] = { "1.2.643.2.52.1.5.1.1", NULL };
......@@ -509,6 +511,12 @@
( ak_function_create_object *) ak_verifykey_create_streebog512, \
( ak_function_destroy_object *) ak_verifykey_destroy, \
NULL, NULL, NULL }
#define ak_object_bckey_belt { sizeof( struct bckey ), \
( ak_function_create_object *) ak_bckey_create_belt, \
( ak_function_destroy_object *) ak_bckey_destroy, \
( ak_function_set_key_object *)ak_bckey_set_key, \
( ak_function_set_key_random_object *)ak_bckey_set_key_random, \
( ak_function_set_key_from_password_object *)ak_bckey_set_key_from_password }
/* ----------------------------------------------------------------------------------------------- */
/*! Константные значения OID библиотеки */
......@@ -580,6 +588,9 @@ static struct oid libakrypt_oids[] =
{ block_cipher, algorithm, asn1_kuznechik_i, asn1_kuznechik_n, NULL,
{ ak_object_bckey_kuznechik, ak_object_undefined, NULL, NULL }},
{ block_cipher, algorithm, asn1_belt_i, asn1_belt_n, NULL,
{ ak_object_bckey_belt, ak_object_undefined, NULL, NULL }},
/* базовые режимы блочного шифрования */
{ block_cipher, encrypt_mode, asn1_ctr_magma_i, asn1_ctr_magma_n, NULL,
{ ak_object_bckey_magma, ak_object_undefined, ( ak_function_run_object *) ak_bckey_ctr,
......
......@@ -734,6 +734,8 @@ extern "C" {
/*! \brief Присвоение ключу алгоритма блочного шифрования значения, выработанного из пароля. */
dll_export int ak_bckey_set_key_from_password( ak_bckey ,
const ak_pointer , const size_t , const ak_pointer , const size_t );
/*! \brief Инициализация секретного ключа алгоритма блочного шифрования Belt. */
dll_export int ak_bckey_create_belt( ak_bckey );
/* ----------------------------------------------------------------------------------------------- */
/*! \brief Функция вырабатывает пару ключей алгоритма блочного шифрования из заданного
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment