From 59e3d340c52a9c45199fd75b96df9e48100ae6e7 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Mon, 3 Feb 2025 20:20:12 +0300
Subject: [PATCH 01/41] merged from main

---
 .gitignore                      |   1 -
 CMakeLists.txt                  |   2 +
 examples/tests/test-belt-hash.c | 177 +++++++++++++
 source/ak_belt_hash.c           | 439 ++++++++++++++++++++++++++++++++
 source/ak_hash.c                |   1 +
 source/ak_oid.c                 |   6 +
 source/libakrypt.h              |  24 +-
 7 files changed, 647 insertions(+), 3 deletions(-)
 create mode 100644 examples/tests/test-belt-hash.c
 create mode 100644 source/ak_belt_hash.c

diff --git a/.gitignore b/.gitignore
index 4b20c12..c10aad4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,4 +6,3 @@ scratch*
 *.kdev4
 tags
 doc/conf.py
-
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3aee7e9..f72f362 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -95,6 +95,7 @@ set( AKRYPT_SOURCES
    source/ak_blom.c
    source/ak_kdf.c
    source/ak_encrypt.c
+   source/ak_belt_hash.c
 )
 
 # -------------------------------------------------------------------------------------------------- #
@@ -336,6 +337,7 @@ set ( ARITHMETIC_TESTS_LIST
       hash02
       kuznechik01
       mac-offset
+      belt-hash
     )
 
 if( AK_TESTS_GMP )
diff --git a/examples/tests/test-belt-hash.c b/examples/tests/test-belt-hash.c
new file mode 100644
index 0000000..28d2c94
--- /dev/null
+++ b/examples/tests/test-belt-hash.c
@@ -0,0 +1,177 @@
+#include <libakrypt.h>
+#include <string.h>
+
+//подстановка битов
+#define H16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)\
+  0x##a, 0x##b, 0x##c, 0x##d, 0x##e, 0x##f, 0x##g, 0x##h,\
+  0x##i, 0x##j, 0x##k, 0x##l, 0x##m, 0x##n, 0x##o, 0x##p
+
+int main( void ) {
+  const ak_uint8 X1[13] = { 
+    0xB1, 0x94, 0xBA, 0xC8, 0x0A, 0x08, 0xF5, 0x3B,
+    0x36, 0x6D, 0x00, 0x8E, 0x58
+  };
+  const ak_uint8 Y1[32] = {
+    H16(AB,EF,97,25,D4,C5,A8,35,97,A3,67,D1,44,94,CC,25),
+    H16(42,F2,0F,65,9D,DF,EC,C9,61,A3,EC,55,0C,BA,8C,75)
+  };
+  const ak_uint8 X2[32] = { 
+    H16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4),
+    H16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D)
+  };
+  const ak_uint8 Y2[32] = {
+    H16(74,9E,4C,36,53,AE,CE,5E,48,DB,47,61,22,77,42,EB),
+    H16(6D,BE,13,F4,A8,0F,7B,EF,F1,A9,CF,8D,10,EE,77,86)
+  };
+  const ak_uint8 X3[48] = { 
+    H16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4),
+    H16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D),
+    H16(5B,E3,D6,12,17,B9,61,81,FE,67,86,AD,71,6B,89,0B)
+  };
+  const ak_uint8 Y3[32] = {
+    H16(9D,02,EE,44,6F,B6,A2,9F,E5,C9,82,D4,B1,3A,F9,D3),
+    H16(E9,08,61,BC,4C,EF,27,CF,30,6B,FB,0B,17,4A,15,4A)
+  };
+
+  ak_uint8 success = 0;
+  ak_uint8 A[32] = {0};
+  struct hash ctx;
+
+  printf("--------------------Testing belt-hash----------------------\n"
+    "               -----------Test 1------------\n"
+    "Input:\n"
+    " > X1 = %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x\n"
+    "Expected output:\n"
+    " > Y1 = %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "        %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n",
+    X1[0] , X1[1] , X1[2] , X1[3] , X1[4] , X1[5] , X1[6] , X1[7] ,
+    X1[8] , X1[9] , X1[10], X1[11], X1[12],
+    Y1[0] , Y1[1] , Y1[2] , Y1[3] , Y1[4] , Y1[5] , Y1[6] , Y1[7] ,
+    Y1[8] , Y1[9] , Y1[10], Y1[11], Y1[12], Y1[13], Y1[14], Y1[15],
+    Y1[16], Y1[17], Y1[18], Y1[19], Y1[20], Y1[21], Y1[22], Y1[23],
+    Y1[24], Y1[25], Y1[26], Y1[27], Y1[28], Y1[29], Y1[30], Y1[31]);
+
+  ak_hash_create_belt_hash( &ctx );
+  ak_hash_ptr( &ctx, X1, 13, A, 32 );
+  ak_hash_destroy( &ctx );
+
+  printf("Output:\n"
+    " > Y1 = %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "        %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n",
+    A[0] , A[1] , A[2] , A[3] , A[4] , A[5] , A[6] , A[7] ,
+    A[8] , A[9] , A[10], A[11], A[12], A[13], A[14], A[15],
+    A[16], A[17], A[18], A[19], A[20], A[21], A[22], A[23],
+    A[24], A[25], A[26], A[27], A[28], A[29], A[30], A[31]);
+  
+  if(strncmp(A, Y1, 32) == 0) {
+    printf("Test 1 was successful\n\n");
+    success += 1;
+    //return 0;
+  }
+  else {
+    printf("Test 1 failed\n\n");
+    //return 1;
+  }
+
+  printf("               -----------Test 2------------\n"
+    "Input:\n"
+    " > X2 = %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "        %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "Expected output:\n"
+    " > Y2 = %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "        %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n",
+    X2[0] , X2[1] , X2[2] , X2[3] , X2[4] , X2[5] , X2[6] , X2[7] ,
+    X2[8] , X2[9] , X2[10], X2[11], X2[12], X2[13], X2[14], X2[15],
+    X2[16], X2[17], X2[18], X2[19], X2[20], X2[21], X2[22], X2[23],
+    X2[24], X2[25], X2[26], X2[27], X2[28], X2[29], X2[30], X2[31],
+    Y2[0] , Y2[1] , Y2[2] , Y2[3] , Y2[4] , Y2[5] , Y2[6] , Y2[7] ,
+    Y2[8] , Y2[9] , Y2[10], Y2[11], Y2[12], Y2[13], Y2[14], Y2[15],
+    Y2[16], Y2[17], Y2[18], Y2[19], Y2[20], Y2[21], Y2[22], Y2[23],
+    Y2[24], Y2[25], Y2[26], Y2[27], Y2[28], Y2[29], Y2[30], Y2[31]);
+
+  ak_hash_create_belt_hash( &ctx );
+  ak_hash_ptr( &ctx, X2, 32, A, 32 );
+  ak_hash_destroy( &ctx );
+
+  printf("Output:\n"
+    " > Y2 = %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "        %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n",
+    A[0] , A[1] , A[2] , A[3] , A[4] , A[5] , A[6] , A[7] ,
+    A[8] , A[9] , A[10], A[11], A[12], A[13], A[14], A[15],
+    A[16], A[17], A[18], A[19], A[20], A[21], A[22], A[23],
+    A[24], A[25], A[26], A[27], A[28], A[29], A[30], A[31]);
+  
+  if(strncmp(A, Y2, 32) == 0) {
+    printf("Test 2 was successful\n\n");
+    success += 2;
+    //return 0;
+  }
+  else {
+    printf("Test 2 failed\n\n");
+    //return 1;
+  }
+
+  printf("               -----------Test 3------------\n"
+    "Input:\n"
+    " > X3 = %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "        %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "        %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "Expected output:\n"
+    " > Y3 = %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "        %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n",
+    X3[0] , X3[1] , X3[2] , X3[3] , X3[4] , X3[5] , X3[6] , X3[7] ,
+    X3[8] , X3[9] , X3[10], X3[11], X3[12], X3[13], X3[14], X3[15],
+    X3[16], X3[17], X3[18], X3[19], X3[20], X3[21], X3[22], X3[23],
+    X3[24], X3[25], X3[26], X3[27], X3[28], X3[29], X3[30], X3[31],
+    X3[32], X3[33], X3[34], X3[35], X3[36], X3[37], X3[38], X3[39],
+    X3[40], X3[41], X3[42], X3[43], X3[44], X3[45], X3[46], X3[47],
+    Y3[0] , Y3[1] , Y3[2] , Y3[3] , Y3[4] , Y3[5] , Y3[6] , Y3[7] ,
+    Y3[8] , Y3[9] , Y3[10], Y3[11], Y3[12], Y3[13], Y3[14], Y3[15],
+    Y3[16], Y3[17], Y3[18], Y3[19], Y3[20], Y3[21], Y3[22], Y3[23],
+    Y3[24], Y3[25], Y3[26], Y3[27], Y3[28], Y3[29], Y3[30], Y3[31]);
+
+  ak_hash_create_belt_hash( &ctx );
+  ak_hash_ptr( &ctx, X2, 48, A, 32 );
+  ak_hash_destroy( &ctx );
+
+  printf("Output:\n"
+    " > Y3 = %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "        %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n",
+    A[0] , A[1] , A[2] , A[3] , A[4] , A[5] , A[6] , A[7] ,
+    A[8] , A[9] , A[10], A[11], A[12], A[13], A[14], A[15],
+    A[16], A[17], A[18], A[19], A[20], A[21], A[22], A[23],
+    A[24], A[25], A[26], A[27], A[28], A[29], A[30], A[31]);
+  
+  if(strncmp(A, Y3, 32) == 0) {
+    printf("Test 3, was successful\n");
+    success += 4;
+    //return 0;
+  }
+  else {
+    printf("Test 3 failed\n");
+    //return 1;
+  }
+
+  if(success == 7) {
+    return EXIT_SUCCESS;
+  }
+  return EXIT_FAILURE;
+}
diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
new file mode 100644
index 0000000..bb22c47
--- /dev/null
+++ b/source/ak_belt_hash.c
@@ -0,0 +1,439 @@
+/* ----------------------------------------------------------------------------------------------- */
+/*                                                                                                 */
+/*  Реализация хэширования сообщения                                                               */
+/*  из Белорусского стандарта СТБ 34.101.31-2020                                                   */
+/*                                                                                                 */
+/* ----------------------------------------------------------------------------------------------- */
+
+#include <libakrypt-internal.h>
+
+//---------------------------------------------------------
+//----------------------belt-block-------------------------
+//---------------------------------------------------------
+
+//подстановка битов
+#define H16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)\
+  0x##a, 0x##b, 0x##c, 0x##d, 0x##e, 0x##f, 0x##g, 0x##h,\
+  0x##i, 0x##j, 0x##k, 0x##l, 0x##m, 0x##n, 0x##o, 0x##p
+
+//базовая H
+static const ak_uint8 H[256] = {
+  H16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4),
+  H16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D),
+  H16(5B,E3,D6,12,17,B9,61,81,FE,67,86,AD,71,6B,89,0B),
+  H16(5C,B0,C0,FF,33,C3,56,B8,35,C4,05,AE,D8,E0,7F,99),
+  H16(E1,2B,DC,1A,E2,82,57,EC,70,3F,CC,F0,95,EE,8D,F1),
+  H16(C1,AB,76,38,9F,E6,78,CA,F7,C6,F8,60,D5,BB,9C,4F),
+  H16(F3,3C,65,7B,63,7C,30,6A,DD,4E,A7,79,9E,B2,3D,31),
+  H16(3E,98,B5,6E,27,D3,BC,CF,59,1E,18,1F,4C,5A,B7,93),
+  H16(E9,DE,E7,2C,8F,0C,0F,A6,2D,DB,49,F4,6F,73,96,47),
+  H16(06,07,53,16,ED,24,7A,37,39,CB,A3,83,03,A9,8B,F6),
+  H16(92,BD,9B,1C,E5,D1,41,01,54,45,FB,C9,5E,4D,0E,F2),
+  H16(68,20,80,AA,22,7D,64,2F,26,87,F9,34,90,40,55,11),
+  H16(BE,32,97,13,43,FC,9A,48,A0,2A,88,5F,19,4B,09,A1),
+  H16(7E,CD,A4,D0,15,44,AF,8C,A5,84,50,BF,66,D2,E8,8A),
+  H16(A2,D7,46,52,42,A8,DF,B3,69,74,C5,51,EB,23,29,21),
+  H16(D4,EF,D9,B4,3A,62,28,75,91,14,10,EA,77,6C,DA,1D),
+};
+
+const ak_uint8* beltH()
+{
+  return H;
+}
+
+//rotl
+#define ROTL32(a, r) \
+  ((ak_uint32)0x##a << r | (ak_uint32)0x##a >> (32 - r))
+#define ROTL32x16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p, r)\
+  ROTL32(a, r), ROTL32(b, r), ROTL32(c, r), ROTL32(d, r),\
+  ROTL32(e, r), ROTL32(f, r), ROTL32(g, r), ROTL32(h, r),\
+  ROTL32(i, r), ROTL32(j, r), ROTL32(k, r), ROTL32(l, r),\
+  ROTL32(m, r), ROTL32(n, r), ROTL32(o, r), ROTL32(p, r)
+
+//rotl(h)
+static const ak_uint32 H5[256] = {
+  ROTL32x16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4, 5),
+  ROTL32x16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D, 5),
+  ROTL32x16(5B,E3,D6,12,17,B9,61,81,FE,67,86,AD,71,6B,89,0B, 5),
+  ROTL32x16(5C,B0,C0,FF,33,C3,56,B8,35,C4,05,AE,D8,E0,7F,99, 5),
+  ROTL32x16(E1,2B,DC,1A,E2,82,57,EC,70,3F,CC,F0,95,EE,8D,F1, 5),
+  ROTL32x16(C1,AB,76,38,9F,E6,78,CA,F7,C6,F8,60,D5,BB,9C,4F, 5),
+  ROTL32x16(F3,3C,65,7B,63,7C,30,6A,DD,4E,A7,79,9E,B2,3D,31, 5),
+  ROTL32x16(3E,98,B5,6E,27,D3,BC,CF,59,1E,18,1F,4C,5A,B7,93, 5),
+  ROTL32x16(E9,DE,E7,2C,8F,0C,0F,A6,2D,DB,49,F4,6F,73,96,47, 5),
+  ROTL32x16(06,07,53,16,ED,24,7A,37,39,CB,A3,83,03,A9,8B,F6, 5),
+  ROTL32x16(92,BD,9B,1C,E5,D1,41,01,54,45,FB,C9,5E,4D,0E,F2, 5),
+  ROTL32x16(68,20,80,AA,22,7D,64,2F,26,87,F9,34,90,40,55,11, 5),
+  ROTL32x16(BE,32,97,13,43,FC,9A,48,A0,2A,88,5F,19,4B,09,A1, 5),
+  ROTL32x16(7E,CD,A4,D0,15,44,AF,8C,A5,84,50,BF,66,D2,E8,8A, 5),
+  ROTL32x16(A2,D7,46,52,42,A8,DF,B3,69,74,C5,51,EB,23,29,21, 5),
+  ROTL32x16(D4,EF,D9,B4,3A,62,28,75,91,14,10,EA,77,6C,DA,1D, 5),
+};
+
+static const ak_uint32 H13[256] = {
+  ROTL32x16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4, 13),
+  ROTL32x16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D, 13),
+  ROTL32x16(5B,E3,D6,12,17,B9,61,81,FE,67,86,AD,71,6B,89,0B, 13),
+  ROTL32x16(5C,B0,C0,FF,33,C3,56,B8,35,C4,05,AE,D8,E0,7F,99, 13),
+  ROTL32x16(E1,2B,DC,1A,E2,82,57,EC,70,3F,CC,F0,95,EE,8D,F1, 13),
+  ROTL32x16(C1,AB,76,38,9F,E6,78,CA,F7,C6,F8,60,D5,BB,9C,4F, 13),
+  ROTL32x16(F3,3C,65,7B,63,7C,30,6A,DD,4E,A7,79,9E,B2,3D,31, 13),
+  ROTL32x16(3E,98,B5,6E,27,D3,BC,CF,59,1E,18,1F,4C,5A,B7,93, 13),
+  ROTL32x16(E9,DE,E7,2C,8F,0C,0F,A6,2D,DB,49,F4,6F,73,96,47, 13),
+  ROTL32x16(06,07,53,16,ED,24,7A,37,39,CB,A3,83,03,A9,8B,F6, 13),
+  ROTL32x16(92,BD,9B,1C,E5,D1,41,01,54,45,FB,C9,5E,4D,0E,F2, 13),
+  ROTL32x16(68,20,80,AA,22,7D,64,2F,26,87,F9,34,90,40,55,11, 13),
+  ROTL32x16(BE,32,97,13,43,FC,9A,48,A0,2A,88,5F,19,4B,09,A1, 13),
+  ROTL32x16(7E,CD,A4,D0,15,44,AF,8C,A5,84,50,BF,66,D2,E8,8A, 13),
+  ROTL32x16(A2,D7,46,52,42,A8,DF,B3,69,74,C5,51,EB,23,29,21, 13),
+  ROTL32x16(D4,EF,D9,B4,3A,62,28,75,91,14,10,EA,77,6C,DA,1D, 13),
+};
+
+static const ak_uint32 H21[256] = {
+  ROTL32x16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4, 21),
+  ROTL32x16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D, 21),
+  ROTL32x16(5B,E3,D6,12,17,B9,61,81,FE,67,86,AD,71,6B,89,0B, 21),
+  ROTL32x16(5C,B0,C0,FF,33,C3,56,B8,35,C4,05,AE,D8,E0,7F,99, 21),
+  ROTL32x16(E1,2B,DC,1A,E2,82,57,EC,70,3F,CC,F0,95,EE,8D,F1, 21),
+  ROTL32x16(C1,AB,76,38,9F,E6,78,CA,F7,C6,F8,60,D5,BB,9C,4F, 21),
+  ROTL32x16(F3,3C,65,7B,63,7C,30,6A,DD,4E,A7,79,9E,B2,3D,31, 21),
+  ROTL32x16(3E,98,B5,6E,27,D3,BC,CF,59,1E,18,1F,4C,5A,B7,93, 21),
+  ROTL32x16(E9,DE,E7,2C,8F,0C,0F,A6,2D,DB,49,F4,6F,73,96,47, 21),
+  ROTL32x16(06,07,53,16,ED,24,7A,37,39,CB,A3,83,03,A9,8B,F6, 21),
+  ROTL32x16(92,BD,9B,1C,E5,D1,41,01,54,45,FB,C9,5E,4D,0E,F2, 21),
+  ROTL32x16(68,20,80,AA,22,7D,64,2F,26,87,F9,34,90,40,55,11, 21),
+  ROTL32x16(BE,32,97,13,43,FC,9A,48,A0,2A,88,5F,19,4B,09,A1, 21),
+  ROTL32x16(7E,CD,A4,D0,15,44,AF,8C,A5,84,50,BF,66,D2,E8,8A, 21),
+  ROTL32x16(A2,D7,46,52,42,A8,DF,B3,69,74,C5,51,EB,23,29,21, 21),
+  ROTL32x16(D4,EF,D9,B4,3A,62,28,75,91,14,10,EA,77,6C,DA,1D, 21),
+};
+
+static const ak_uint32 H29[256] = {
+  ROTL32x16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4, 29),
+  ROTL32x16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D, 29),
+  ROTL32x16(5B,E3,D6,12,17,B9,61,81,FE,67,86,AD,71,6B,89,0B, 29),
+  ROTL32x16(5C,B0,C0,FF,33,C3,56,B8,35,C4,05,AE,D8,E0,7F,99, 29),
+  ROTL32x16(E1,2B,DC,1A,E2,82,57,EC,70,3F,CC,F0,95,EE,8D,F1, 29),
+  ROTL32x16(C1,AB,76,38,9F,E6,78,CA,F7,C6,F8,60,D5,BB,9C,4F, 29),
+  ROTL32x16(F3,3C,65,7B,63,7C,30,6A,DD,4E,A7,79,9E,B2,3D,31, 29),
+  ROTL32x16(3E,98,B5,6E,27,D3,BC,CF,59,1E,18,1F,4C,5A,B7,93, 29),
+  ROTL32x16(E9,DE,E7,2C,8F,0C,0F,A6,2D,DB,49,F4,6F,73,96,47, 29),
+  ROTL32x16(06,07,53,16,ED,24,7A,37,39,CB,A3,83,03,A9,8B,F6, 29),
+  ROTL32x16(92,BD,9B,1C,E5,D1,41,01,54,45,FB,C9,5E,4D,0E,F2, 29),
+  ROTL32x16(68,20,80,AA,22,7D,64,2F,26,87,F9,34,90,40,55,11, 29),
+  ROTL32x16(BE,32,97,13,43,FC,9A,48,A0,2A,88,5F,19,4B,09,A1, 29),
+  ROTL32x16(7E,CD,A4,D0,15,44,AF,8C,A5,84,50,BF,66,D2,E8,8A, 29),
+  ROTL32x16(A2,D7,46,52,42,A8,DF,B3,69,74,C5,51,EB,23,29,21, 29),
+  ROTL32x16(D4,EF,D9,B4,3A,62,28,75,91,14,10,EA,77,6C,DA,1D, 29),
+};
+
+//gr(x)
+#define G5(x)\
+  H5[(x) & 255] ^ H13[(x) >> 8 & 255] ^ \
+  H21[(x) >> 16 & 255] ^ H29[(x) >> 24]
+#define G13(x)\
+  H13[(x) & 255] ^ H21[(x) >> 8 & 255] ^ \
+  H29[(x) >> 16 & 255] ^ H5[(x) >> 24]
+#define G21(x)\
+  H21[(x) & 255] ^ H29[(x) >> 8 & 255] ^ \
+  H5[(x) >> 16 & 255] ^ H13[(x) >> 24]
+
+//1 раунд
+#define R(a, b, c, d, K, i, subkey)\
+  *b ^= G5(*a + subkey(K, i, 0));\
+  *c ^= G21(*d + subkey(K, i, 1));\
+  *a -= G13(*b + subkey(K, i, 2));\
+  *c += *b;\
+  *b += G21(*c + subkey(K, i, 3)) ^ i;\
+  *c -= *b;\
+  *d += G13(*c + subkey(K, i, 4));\
+  *b ^= G21(*a + subkey(K, i, 5));\
+  *c ^= G5(*d + subkey(K, i, 6));\
+
+//ключевая развертка
+#define subkey_e(K, i, j) K[(7 * (i) - 7 + (j)) % 8]
+
+//зашифрование с перестановкой через аргументы
+#define E(a, b, c, d, K)\
+  R(a, b, c, d, K, 1, subkey_e);\
+  R(b, d, a, c, K, 2, subkey_e);\
+  R(d, c, b, a, K, 3, subkey_e);\
+  R(c, a, d, b, K, 4, subkey_e);\
+  R(a, b, c, d, K, 5, subkey_e);\
+  R(b, d, a, c, K, 6, subkey_e);\
+  R(d, c, b, a, K, 7, subkey_e);\
+  R(c, a, d, b, K, 8, subkey_e);\
+  *a ^= *b, *b ^= *a, *a ^= *b;\
+  *c ^= *d, *d ^= *c, *c ^= *d;\
+  *b ^= *c, *c ^= *b, *b ^= *c;\
+
+/**
+ * \brief Алгоритм шифрования belt-block.
+ * \param block [4*32 бит] Указатель на шифруемый блок данных.
+ * \param key [8*32 бит] Указатель на ключ шифрования.
+ */
+void beltBlockEncr2(ak_uint32 block[4], const ak_uint32 key[8])
+{
+  E((block + 0), (block + 1), (block + 2), (block + 3), key);
+}
+
+//---------------------------------------------------------
+//--------------------belt-compress------------------------
+//---------------------------------------------------------
+
+#define beltBlockNeg(dest, src)\
+  ((ak_uint32*)(dest))[0] = ~((const ak_uint32*)(src))[0],\
+  ((ak_uint32*)(dest))[1] = ~((const ak_uint32*)(src))[1],\
+  ((ak_uint32*)(dest))[2] = ~((const ak_uint32*)(src))[2],\
+  ((ak_uint32*)(dest))[3] = ~((const ak_uint32*)(src))[3]
+
+#define beltBlockXor(dest, src1, src2)\
+  ((ak_uint32*)(dest))[0] = \
+    ((const ak_uint32*)(src1))[0] ^ ((const ak_uint32*)(src2))[0],\
+  ((ak_uint32*)(dest))[1] = \
+    ((const ak_uint32*)(src1))[1] ^ ((const ak_uint32*)(src2))[1],\
+  ((ak_uint32*)(dest))[2] = \
+    ((const ak_uint32*)(src1))[2] ^ ((const ak_uint32*)(src2))[2],\
+  ((ak_uint32*)(dest))[3] = \
+    ((const ak_uint32*)(src1))[3] ^ ((const ak_uint32*)(src2))[3]
+
+#define beltBlockXor2(dest, src)\
+  ((ak_uint32*)(dest))[0] ^= ((const ak_uint32*)(src))[0],\
+  ((ak_uint32*)(dest))[1] ^= ((const ak_uint32*)(src))[1],\
+  ((ak_uint32*)(dest))[2] ^= ((const ak_uint32*)(src))[2],\
+  ((ak_uint32*)(dest))[3] ^= ((const ak_uint32*)(src))[3]
+
+#define beltBlockCopy(dest, src)\
+  ((ak_uint32*)(dest))[0] = ((const ak_uint32*)(src))[0],\
+  ((ak_uint32*)(dest))[1] = ((const ak_uint32*)(src))[1],\
+  ((ak_uint32*)(dest))[2] = ((const ak_uint32*)(src))[2],\
+  ((ak_uint32*)(dest))[3] = ((const ak_uint32*)(src))[3]
+
+/**
+ * \brief Алгоритм сжатия belt-compress без обработки S
+ * \param h [8*32 бит] Указатель на выходное значение Y <b>и второй половины входного значения X</b>.
+ * \param X [8*32 бит] Указатель на входное значение первой половины данных X.
+ * \param stack [12*32 бит] Указатель на промежуточный буфер работы функции.
+ */
+void beltCompress(ak_uint32 h[8], const ak_uint32 X[8], void* stack)
+{
+  // [12]buf = [4]buf0 || [4]buf1 || [4]buf2
+  ak_uint32* buf = (ak_uint32*)stack;
+  // буферы не пересекаются?
+  //ASSERT(memIsDisjoint3(h, 32, X, 32, buf, 48));
+  // buf0, buf1 <- h0 + h1
+  beltBlockXor(buf, h, h + 4);
+  beltBlockCopy(buf + 4, buf);
+  // buf0 <- beltBlock(buf0, X) + buf1
+  beltBlockEncr2(buf, X);
+  beltBlockXor2(buf, buf + 4);
+  // buf2 <- h0
+  beltBlockCopy(buf + 8, h);
+  // buf1 <- h1 [buf01 == K1]
+  beltBlockCopy(buf + 4, h + 4);
+  // h0 <- beltBlock(X0, buf01) + X0
+  beltBlockCopy(h, X);
+  beltBlockEncr2(h, buf);
+  beltBlockXor2(h, X);
+  // buf1 <- ~buf0 [buf12 == K2]
+  beltBlockNeg(buf + 4, buf);
+  // h1 <- beltBlock(X1, buf12) + X1
+  beltBlockCopy(h + 4, X + 4);
+  beltBlockEncr2(h + 4, buf + 4);
+  beltBlockXor2(h + 4, X + 4);
+}
+
+/**
+ * \brief Алгоритм сжатия belt-compress.
+ * \param s [4*32 бит] Указатель на выходное значение данных S.
+ * \param h [8*32 бит] Указатель на выходное значение Y <b>и второй половины входного значения X</b>.
+ * \param X [8*32 бит] Указатель на входное значение первой половины данных X.
+ * \param stack [12*32 бит] Указатель на промежуточный буфер работы функции.
+ */
+static inline void beltCompress2(ak_uint32 s[4], ak_uint32 h[8],
+                   const ak_uint32 X[8], void* stack)
+{
+  // [12]buf = [4]buf0 || [4]buf1 || [4]buf2
+  ak_uint32* buf = (ak_uint32*)stack;
+  // буферы не пересекаются?
+  //ASSERT(memIsDisjoint4(s, 16, h, 32, X, 32, buf, 48));
+  // buf0, buf1 <- h0 + h1
+  beltBlockXor(buf, h, h + 4);
+  beltBlockCopy(buf + 4, buf);
+  // buf0 <- beltBlock(buf0, X) + buf1
+  beltBlockEncr2(buf, X);
+  beltBlockXor2(buf, buf + 4);
+  // s <- s ^ buf0
+  beltBlockXor2(s, buf);
+  // buf2 <- h0
+  beltBlockCopy(buf + 8, h);
+  // buf1 <- h1 [buf01 == K1]
+  beltBlockCopy(buf + 4, h + 4);
+  // h0 <- beltBlock(X0, buf01) + X0
+  beltBlockCopy(h, X);
+  beltBlockEncr2(h, buf);
+  beltBlockXor2(h, X);
+  // buf1 <- ~buf0 [buf12 == K2]
+  beltBlockNeg(buf + 4, buf);
+  // h1 <- beltBlock(X1, buf12) + X1
+  beltBlockCopy(h + 4, X + 4);
+  beltBlockEncr2(h + 4, buf + 4);
+  beltBlockXor2(h + 4, X + 4);
+}
+
+//---------------------------------------------------------
+//----------------------belt-hash--------------------------
+//---------------------------------------------------------
+
+#define beltBlockSetZero(block)\
+  ((ak_uint32*)(block))[0] = 0,\
+  ((ak_uint32*)(block))[1] = 0,\
+  ((ak_uint32*)(block))[2] = 0,\
+  ((ak_uint32*)(block))[3] = 0
+
+ak_uint32 u32Rev(ak_uint32 w) {
+  return w << 24 | (w & 0xFF00) << 8 | (w >> 8 & 0xFF00) | w >> 24;
+}
+
+#define beltBlockRevU32(block)\
+  ((ak_uint32*)(block))[0] = u32Rev(((ak_uint32*)(block))[0]),\
+  ((ak_uint32*)(block))[1] = u32Rev(((ak_uint32*)(block))[1]),\
+  ((ak_uint32*)(block))[2] = u32Rev(((ak_uint32*)(block))[2]),\
+  ((ak_uint32*)(block))[3] = u32Rev(((ak_uint32*)(block))[3])
+
+// size_t beltHash_keep()
+// {
+//  return sizeof(belt_hash_st)/* + 12*4*/;
+// }
+
+
+
+
+
+
+
+ static int ak_hash_context_belt_hash_clean( ak_pointer bctx )
+{
+  ak_belt_hash cx = ( ak_belt_hash ) bctx;
+  if( cx == NULL ) return ak_error_null_pointer;
+
+  beltBlockSetZero(cx->ls);
+  beltBlockSetZero(cx->ls + 4);
+  // h <- B194...0D
+  memmove(cx->h, beltH(), 32);
+  // нет накопленнных данных
+  cx->filled = 0;
+
+ return ak_error_ok;
+}
+
+ static int ak_hash_context_belt_hash_update(
+  ak_pointer bctx, const ak_pointer in, const size_t size )
+{
+  ak_belt_hash cx = ( ak_belt_hash ) bctx;
+  const ak_uint8* dt = (const ak_uint8*) in;
+  ak_uint32 count = (ak_uint32) size;
+  ak_uint32 carry = count << 3;
+
+  if( cx == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
+                                               "using null pointer to internal streebog context" );
+  if(( !size ) || ( in == NULL )) return ak_error_ok;
+
+  // обновить длину
+  carry = (cx->ls[0] += carry) < carry;
+  carry = (cx->ls[1] += carry) < carry;
+  carry = (cx->ls[2] += carry) < carry;
+  cx->ls[3] += carry;
+
+  // накопленных данных на этот момент не предполагается,
+  // потому сразу в цикл по блокам
+  // цикл по полным блокам
+  while (count >= 32)
+  {
+    beltBlockCopy(cx->block, dt);
+    beltBlockCopy(cx->block + 16, dt + 16);
+#ifndef AK_LITTLE_ENDIAN
+    beltBlockRevU32(st->block);
+    beltBlockRevU32(st->block + 16);
+#endif
+    beltCompress2(cx->ls + 4, cx->h, (ak_uint32*)cx->block, cx->stack);
+    dt += 32;
+    count -= 32;
+  }
+
+  return ak_error_ok;
+}
+
+ static int ak_hash_context_streebog_finalize( ak_pointer bctx,
+  const ak_pointer in, const size_t size, ak_pointer out,
+  const size_t out_size )
+{
+  ak_belt_hash cx = ( ak_belt_hash ) bctx;
+  const ak_uint8* dt = (const ak_uint8*) in;
+  ak_uint8 m[32];
+  struct belt_hash bx; /* структура для хранения копии текущего состояния контекста */
+
+  if( cx == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
+                                               "using null pointer to internal streebog context" );
+  if( out == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
+                                                   "using null pointer to externl result buffer" );
+  if( size >= 32 ) return ak_error_message( ak_error_wrong_length, __func__,
+                                                                       "input length is too huge" );
+  // /* формируем временный текст */
+  memset(m, 0, 32);
+  if(in != NULL)
+    memcpy(m, in, ( ak_uint32 )size);
+
+  /* при финализации мы изменяем копию существующей структуры */
+  memcpy( &bx, cx, sizeof( struct belt_hash ));
+#ifndef AK_LITTLE_ENDIAN
+  beltBlockRevU32(m);
+  beltBlockRevU32(m + 16);
+#endif
+  beltCompress2(bx->ls + 4, bx->h, (uint32_t*)m, bx->stack);
+#ifndef AK_LITTLE_ENDIAN
+  beltBlockRevU32(m + 16);
+  beltBlockRevU32(m);
+#endif
+  beltCompress(bx->h, bx->ls, bx->stack);
+  // ak_hash_context_streebog_g( &sx, sx.n, m );
+  // ak_hash_context_streebog_add( &sx, size << 3 );
+  // ak_hash_context_streebog_sadd( &sx, m );
+  // ak_hash_context_streebog_g( &sx, NULL, sx.n );
+  // ak_hash_context_streebog_g( &sx, NULL, sx.sigma );
+
+ /* копируем нужную часть результирующего массива или выдаем сообщение об ошибке */
+  memcpy(hash, st->h, ak_min(32, out_size));
+
+ return ak_error_ok;
+}
+
+ int ak_hash_create_belt_hash( ak_hash hctx )
+{
+  ak_uint8 out[32];
+  int error = ak_error_ok;
+
+  if( hctx == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
+                                                            "using null pointer to hash context" );
+  if(( hctx->oid = ak_oid_find_by_name( "belt-hash" )) == NULL )
+    return ak_error_message( ak_error_wrong_oid, __func__,
+                                           "incorrect internal search of belt-hash identifier" );
+  if(( error = ak_mac_create( &hctx->mctx, 32, &hctx->data.sctx,
+                                             ak_hash_context_belt_hash_clean,
+                                             ak_hash_context_belt_hash_update,
+                                             ak_hash_context_belt_hash_finalize )) != ak_error_ok )
+    return ak_error_message( error, __func__, "incorrect initialization of internal mac context" );
+
+ // /* добавочная проверка корректной работы алгоритма хэширования */
+ //  if( ak_libakrypt_get_option_by_name( "use_additional_algorithm_check_context" ) == ak_true ) {
+ //    ak_hash_context_streebog_clean( &hctx->data.sctx );
+ //    if(( error = ak_hash_ptr( hctx, streebog_M1_message, 63, out, sizeof( out ))) != ak_error_ok )
+ //      return ak_error_message( error, __func__ , "invalid calculation of streebog256 code" );
+
+ //    if( ak_ptr_is_equal_with_log( out, streebog256_testM1, sizeof( out )) != ak_true )
+ //      return ak_error_message( ak_error_not_equal_data, __func__ ,
+ //                                             "the 1st test from GOST R 34.11-2012 is wrong" );
+ //  }
+
+  return ak_hash_context_streebog_clean( &hctx->data.bctx );
+}
diff --git a/source/ak_hash.c b/source/ak_hash.c
index f6e6149..82bcd0a 100644
--- a/source/ak_hash.c
+++ b/source/ak_hash.c
@@ -1513,6 +1513,7 @@
                                                        "destroying null pointer to hash context" );
   hctx->oid = NULL;
   memset( &hctx->data.sctx, 0, sizeof( struct streebog ));
+  memset( &hctx->data.bctx, 0, sizeof( struct belt_hash ));
   if( ak_mac_destroy( &hctx->mctx ) != ak_error_ok )
     ak_error_message( ak_error_get_value(), __func__,
                                                     "incorrect cleaning of internal mac context" );
diff --git a/source/ak_oid.c b/source/ak_oid.c
index 9411cd8..b0921f3 100644
--- a/source/ak_oid.c
+++ b/source/ak_oid.c
@@ -69,6 +69,8 @@
  static const char *asn1_streebog256_i[] = { "1.2.643.7.1.1.2.2", NULL };
  static const char *asn1_streebog512_n[] = { "streebog512", "md_gost12_512", NULL };
  static const char *asn1_streebog512_i[] = { "1.2.643.7.1.1.2.3", NULL };
+ static const char *asn1_belt_hash_n[] = { "belt-hash", NULL };
+ static const char *asn1_belt_hash_i[] = { "1.2.112.0.2.0.34.101.31.81", NULL };
  static const char *asn1_crc64_n[] =       { "crc64", NULL };
  static const char *asn1_crc64_i[] =       { "1.2.643.2.52.1.2.2", NULL };
 
@@ -556,6 +558,10 @@ static struct oid libakrypt_oids[] =
   {{ sizeof( struct hash ), ( ak_function_create_object *) ak_hash_create_streebog512,
                               ( ak_function_destroy_object *) ak_hash_destroy, NULL, NULL, NULL },
                               ak_object_undefined, (ak_function_run_object *) ak_hash_ptr, NULL }},
+ { hash_function, algorithm, asn1_belt_hash_i, asn1_belt_hash_n, NULL,
+  {{ sizeof( struct hash ), ( ak_function_create_object *) ak_hash_create_belt_hash,
+                              ( ak_function_destroy_object *) ak_hash_destroy, NULL, NULL, NULL },
+                              ak_object_undefined, (ak_function_run_object *) ak_hash_ptr, NULL }},
 
  { hash_function, algorithm, asn1_crc64_i, asn1_crc64_n, NULL,
   {{ sizeof( struct hash ), ( ak_function_create_object *) ak_hash_create_crc64,
diff --git a/source/libakrypt.h b/source/libakrypt.h
index 9bcbf75..0e525b5 100644
--- a/source/libakrypt.h
+++ b/source/libakrypt.h
@@ -701,7 +701,7 @@ extern "C" {
   /*! \brief Указатель на секретный ключ. */
    struct skey key;
   /*! \brief Размер блока обрабатываемых данных (в байтах). */
-   size_t bsize;
+   size_t size;
   /*! \brief Буффер, для хранения текущего значения синхропосылки.
       \details Максимальное количество блоков, помещающихся в буффер,
       равно 8 для Магмы и 4 для Кузнечика. */
@@ -881,6 +881,22 @@ extern "C" {
   size_t hsize;
 } *ak_streebog;
 
+/* ----------------------------------------------------------------------------------------------- */
+/*! \brief Структура для хранения внутренних данных функции хеширования семейства Стрибогbelt-hash
+/* ----------------------------------------------------------------------------------------------- */
+ typedef struct belt_hash {
+  /*! \brief Блок [4]len || [4]s */
+  ak_uint32 ls[8];
+  /*! \brief Временное значение хэш-суммы */
+  ak_uint32 h[8];
+  /*! \brief Блок данных для шифрования */
+  ak_uint8 block[32];
+  /*! \brief Оставшиеся октеты в блоке */
+  size_t filled;
+  /*! \brief Стек для работы beltCompr [12*4 байт] */
+  ak_uint8 stack[12*4];
+} *ak_belt_hash;
+
 /* ----------------------------------------------------------------------------------------------- */
 /*! \brief Контекст бесключевой функции хеширования. */
 /*! \details Класс предоставляет интерфейс для реализации бесключевых функций хеширования, построенных
@@ -891,7 +907,7 @@ extern "C" {
 
   Перед началом работы контекст функции хэширования должен быть инициализирован
   вызовом одной из функций инициализации, например, функции ak_hash_create_streebog256()
-  или функции ak_hash_create_streebog512().
+  или функции ak_ak_oid_find_by_name_create_streebog512().
   После завершения вычислений контекст должен быть освобожден с помощью функции
   ak_hash_destroy().                                                                       */
 /* ----------------------------------------------------------------------------------------------- */
@@ -904,6 +920,8 @@ extern "C" {
    union {
      /*! \brief Структура алгоритмов семейства Стрибог. */
       struct streebog sctx;
+     /*! \brief Структура алгоритма belt-hash. */
+      struct belt_hash bctx;
      /*! \brief Вектор значений для алгоритмов семейства crc64 */
       ak_uint64 b64;
    } data;
@@ -914,6 +932,8 @@ extern "C" {
  dll_export int ak_hash_create_streebog256( ak_hash );
 /*! \brief Инициализация контекста функции бесключевого хеширования ГОСТ Р 34.11-2012 (Стрибог512). */
  dll_export int ak_hash_create_streebog512( ak_hash );
+/*! \brief Инициализация контекста функции бесключевого хеширования СТБ 34.101.31-2020 (belt-hash). */
+ dll_export int ak_hash_create_belt_hash( ak_hash );
 /*! \brief Инициализация контекста некриптографической функции хеширования crc64. */
  dll_export int ak_hash_create_crc64( ak_hash );
 /*! \brief Инициализация контекста функции бесключевого хеширования по заданному OID алгоритма. */
-- 
GitLab


From cac79a468ee5efa0c2060ed1e7cf3685540a9080 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Mon, 3 Feb 2025 20:38:52 +0300
Subject: [PATCH 02/41] small fixes

---
 source/ak_hmac.c   | 2 +-
 source/libakrypt.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/source/ak_hmac.c b/source/ak_hmac.c
index 8e62fd6..45e5db2 100644
--- a/source/ak_hmac.c
+++ b/source/ak_hmac.c
@@ -712,7 +712,7 @@
  /* теперь контекст двойного алгоритма (шифрование + имитозащита) */
    ctx->tag_size = ((ak_hmac)ctx->authenticationKey)->ctx.data.sctx.hsize; /* размер имитовставки */
    ctx->block_size = ((ak_hmac)ctx->authenticationKey)->mctx.bsize; /* размер блока входных данных */
-   ctx->iv_size = ( crf == ak_true ) ? ((ak_bckey)ctx->encryptionKey)->bsize >> 1 : 0; /* размер синхропосылки */
+   ctx->iv_size = ( crf == ak_true ) ? ((ak_bckey)ctx->encryptionKey)->mctx.bsize >> 1 : 0; /* размер синхропосылки */
    ctx->auth_clean = ak_ctr_hmac_authentication_clean;
    ctx->auth_update = ak_ctr_hmac_authentication_update;
    ctx->auth_finalize = ak_ctr_hmac_authentication_finalize;
diff --git a/source/libakrypt.h b/source/libakrypt.h
index 0e525b5..16fc024 100644
--- a/source/libakrypt.h
+++ b/source/libakrypt.h
@@ -882,7 +882,7 @@ extern "C" {
 } *ak_streebog;
 
 /* ----------------------------------------------------------------------------------------------- */
-/*! \brief Структура для хранения внутренних данных функции хеширования семейства Стрибогbelt-hash
+/*! \brief Структура для хранения внутренних данных функции хеширования семейства belt-hash */
 /* ----------------------------------------------------------------------------------------------- */
  typedef struct belt_hash {
   /*! \brief Блок [4]len || [4]s */
-- 
GitLab


From 4df7b268b5b763020a3180cebce35995f7797400 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Mon, 3 Feb 2025 20:41:04 +0300
Subject: [PATCH 03/41] small fixes x2

---
 source/ak_hmac.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source/ak_hmac.c b/source/ak_hmac.c
index 45e5db2..955585c 100644
--- a/source/ak_hmac.c
+++ b/source/ak_hmac.c
@@ -712,7 +712,7 @@
  /* теперь контекст двойного алгоритма (шифрование + имитозащита) */
    ctx->tag_size = ((ak_hmac)ctx->authenticationKey)->ctx.data.sctx.hsize; /* размер имитовставки */
    ctx->block_size = ((ak_hmac)ctx->authenticationKey)->mctx.bsize; /* размер блока входных данных */
-   ctx->iv_size = ( crf == ak_true ) ? ((ak_bckey)ctx->encryptionKey)->mctx.bsize >> 1 : 0; /* размер синхропосылки */
+   ctx->iv_size = ( crf == ak_true ) ? ((ak_bckey)ctx->encryptionKey)->size >> 1 : 0; /* размер синхропосылки */
    ctx->auth_clean = ak_ctr_hmac_authentication_clean;
    ctx->auth_update = ak_ctr_hmac_authentication_update;
    ctx->auth_finalize = ak_ctr_hmac_authentication_finalize;
-- 
GitLab


From 6470a7e782f37fb6c12dab413d6d823924a53e76 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=A2=D1=83=D1=80=20=D0=A2=D0=B8=D0=BC=D0=BE=D1=84=D0=B5?=
 =?UTF-8?q?=D0=B9=20=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=D0=BE?=
 =?UTF-8?q?=D0=B2=D0=B8=D1=87?= <tvtur@edu.hse.ru>
Date: Mon, 3 Feb 2025 17:56:33 +0000
Subject: [PATCH 04/41] Revert "small fixes x2"

This reverts commit 4df7b268b5b763020a3180cebce35995f7797400
---
 source/ak_hmac.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source/ak_hmac.c b/source/ak_hmac.c
index 955585c..45e5db2 100644
--- a/source/ak_hmac.c
+++ b/source/ak_hmac.c
@@ -712,7 +712,7 @@
  /* теперь контекст двойного алгоритма (шифрование + имитозащита) */
    ctx->tag_size = ((ak_hmac)ctx->authenticationKey)->ctx.data.sctx.hsize; /* размер имитовставки */
    ctx->block_size = ((ak_hmac)ctx->authenticationKey)->mctx.bsize; /* размер блока входных данных */
-   ctx->iv_size = ( crf == ak_true ) ? ((ak_bckey)ctx->encryptionKey)->size >> 1 : 0; /* размер синхропосылки */
+   ctx->iv_size = ( crf == ak_true ) ? ((ak_bckey)ctx->encryptionKey)->mctx.bsize >> 1 : 0; /* размер синхропосылки */
    ctx->auth_clean = ak_ctr_hmac_authentication_clean;
    ctx->auth_update = ak_ctr_hmac_authentication_update;
    ctx->auth_finalize = ak_ctr_hmac_authentication_finalize;
-- 
GitLab


From 7d67dbd71d655fd5d54d6e7c0d0a63d2c9767105 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=A2=D1=83=D1=80=20=D0=A2=D0=B8=D0=BC=D0=BE=D1=84=D0=B5?=
 =?UTF-8?q?=D0=B9=20=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=D0=BE?=
 =?UTF-8?q?=D0=B2=D0=B8=D1=87?= <tvtur@edu.hse.ru>
Date: Mon, 3 Feb 2025 17:56:45 +0000
Subject: [PATCH 05/41] Revert "small fixes"

This reverts commit cac79a468ee5efa0c2060ed1e7cf3685540a9080
---
 source/ak_hmac.c   | 2 +-
 source/libakrypt.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/source/ak_hmac.c b/source/ak_hmac.c
index 45e5db2..8e62fd6 100644
--- a/source/ak_hmac.c
+++ b/source/ak_hmac.c
@@ -712,7 +712,7 @@
  /* теперь контекст двойного алгоритма (шифрование + имитозащита) */
    ctx->tag_size = ((ak_hmac)ctx->authenticationKey)->ctx.data.sctx.hsize; /* размер имитовставки */
    ctx->block_size = ((ak_hmac)ctx->authenticationKey)->mctx.bsize; /* размер блока входных данных */
-   ctx->iv_size = ( crf == ak_true ) ? ((ak_bckey)ctx->encryptionKey)->mctx.bsize >> 1 : 0; /* размер синхропосылки */
+   ctx->iv_size = ( crf == ak_true ) ? ((ak_bckey)ctx->encryptionKey)->bsize >> 1 : 0; /* размер синхропосылки */
    ctx->auth_clean = ak_ctr_hmac_authentication_clean;
    ctx->auth_update = ak_ctr_hmac_authentication_update;
    ctx->auth_finalize = ak_ctr_hmac_authentication_finalize;
diff --git a/source/libakrypt.h b/source/libakrypt.h
index 16fc024..0e525b5 100644
--- a/source/libakrypt.h
+++ b/source/libakrypt.h
@@ -882,7 +882,7 @@ extern "C" {
 } *ak_streebog;
 
 /* ----------------------------------------------------------------------------------------------- */
-/*! \brief Структура для хранения внутренних данных функции хеширования семейства belt-hash */
+/*! \brief Структура для хранения внутренних данных функции хеширования семейства Стрибогbelt-hash
 /* ----------------------------------------------------------------------------------------------- */
  typedef struct belt_hash {
   /*! \brief Блок [4]len || [4]s */
-- 
GitLab


From becf4b629cd3946ebd8f84872bea64a48fd30a55 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Mon, 3 Feb 2025 21:05:11 +0300
Subject: [PATCH 06/41] small fixes x3

---
 source/libakrypt.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/source/libakrypt.h b/source/libakrypt.h
index 0e525b5..d099e01 100644
--- a/source/libakrypt.h
+++ b/source/libakrypt.h
@@ -701,7 +701,7 @@ extern "C" {
   /*! \brief Указатель на секретный ключ. */
    struct skey key;
   /*! \brief Размер блока обрабатываемых данных (в байтах). */
-   size_t size;
+   size_t bsize;
   /*! \brief Буффер, для хранения текущего значения синхропосылки.
       \details Максимальное количество блоков, помещающихся в буффер,
       равно 8 для Магмы и 4 для Кузнечика. */
@@ -882,7 +882,7 @@ extern "C" {
 } *ak_streebog;
 
 /* ----------------------------------------------------------------------------------------------- */
-/*! \brief Структура для хранения внутренних данных функции хеширования семейства Стрибогbelt-hash
+/*! \brief Структура для хранения внутренних данных функции хеширования семейства belt-hash */
 /* ----------------------------------------------------------------------------------------------- */
  typedef struct belt_hash {
   /*! \brief Блок [4]len || [4]s */
-- 
GitLab


From 758780e58572e13d5b25132e8f54c8f7bc4b3a06 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Mon, 3 Feb 2025 21:11:59 +0300
Subject: [PATCH 07/41] small mine fixes

---
 source/ak_belt_hash.c | 15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index bb22c47..50d7aad 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -381,8 +381,8 @@ ak_uint32 u32Rev(ak_uint32 w) {
                                                                        "input length is too huge" );
   // /* формируем временный текст */
   memset(m, 0, 32);
-  if(in != NULL)
-    memcpy(m, in, ( ak_uint32 )size);
+  if(dt != NULL)
+    memcpy(m, dt, ( ak_uint32 )size);
 
   /* при финализации мы изменяем копию существующей структуры */
   memcpy( &bx, cx, sizeof( struct belt_hash ));
@@ -390,12 +390,12 @@ ak_uint32 u32Rev(ak_uint32 w) {
   beltBlockRevU32(m);
   beltBlockRevU32(m + 16);
 #endif
-  beltCompress2(bx->ls + 4, bx->h, (uint32_t*)m, bx->stack);
+  beltCompress2(bx.ls + 4, bx.h, (ak_uint32*)m, bx.stack);
 #ifndef AK_LITTLE_ENDIAN
   beltBlockRevU32(m + 16);
   beltBlockRevU32(m);
 #endif
-  beltCompress(bx->h, bx->ls, bx->stack);
+  beltCompress(bx.h, bx.ls, bx.stack);
   // ak_hash_context_streebog_g( &sx, sx.n, m );
   // ak_hash_context_streebog_add( &sx, size << 3 );
   // ak_hash_context_streebog_sadd( &sx, m );
@@ -403,16 +403,13 @@ ak_uint32 u32Rev(ak_uint32 w) {
   // ak_hash_context_streebog_g( &sx, NULL, sx.sigma );
 
  /* копируем нужную часть результирующего массива или выдаем сообщение об ошибке */
-  memcpy(hash, st->h, ak_min(32, out_size));
+  memcpy(out, bx.h, ak_min(32, out_size));
 
  return ak_error_ok;
 }
 
  int ak_hash_create_belt_hash( ak_hash hctx )
 {
-  ak_uint8 out[32];
-  int error = ak_error_ok;
-
   if( hctx == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
                                                             "using null pointer to hash context" );
   if(( hctx->oid = ak_oid_find_by_name( "belt-hash" )) == NULL )
@@ -435,5 +432,5 @@ ak_uint32 u32Rev(ak_uint32 w) {
  //                                             "the 1st test from GOST R 34.11-2012 is wrong" );
  //  }
 
-  return ak_hash_context_streebog_clean( &hctx->data.bctx );
+  return ak_hash_context_belt_hash_clean( &hctx->data.bctx );
 }
-- 
GitLab


From b5160d47df41b25c13156b65e6e464381a225dd3 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Mon, 3 Feb 2025 21:14:12 +0300
Subject: [PATCH 08/41] small mine fixes x2

---
 source/ak_belt_hash.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index 50d7aad..a1d596a 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -364,7 +364,7 @@ ak_uint32 u32Rev(ak_uint32 w) {
   return ak_error_ok;
 }
 
- static int ak_hash_context_streebog_finalize( ak_pointer bctx,
+ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
   const ak_pointer in, const size_t size, ak_pointer out,
   const size_t out_size )
 {
@@ -410,6 +410,8 @@ ak_uint32 u32Rev(ak_uint32 w) {
 
  int ak_hash_create_belt_hash( ak_hash hctx )
 {
+  int error = ak_error_ok;
+
   if( hctx == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
                                                             "using null pointer to hash context" );
   if(( hctx->oid = ak_oid_find_by_name( "belt-hash" )) == NULL )
-- 
GitLab


From 761999cb3318e931f492e46d6f11b72e805d1f3c Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Mon, 3 Feb 2025 23:13:36 +0300
Subject: [PATCH 09/41] testing test fixes

---
 examples/tests/test-belt-hash.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/examples/tests/test-belt-hash.c b/examples/tests/test-belt-hash.c
index 28d2c94..b4cb248 100644
--- a/examples/tests/test-belt-hash.c
+++ b/examples/tests/test-belt-hash.c
@@ -37,6 +37,9 @@ int main( void ) {
   ak_uint8 A[32] = {0};
   struct hash ctx;
 
+  ak_log_set_level( ak_log_none );
+  ak_libakrypt_create( ak_function_log_stderr );
+
   printf("--------------------Testing belt-hash----------------------\n"
     "               -----------Test 1------------\n"
     "Input:\n"
@@ -150,6 +153,8 @@ int main( void ) {
   ak_hash_ptr( &ctx, X2, 48, A, 32 );
   ak_hash_destroy( &ctx );
 
+  ak_libakrypt_destroy();
+
   printf("Output:\n"
     " > Y3 = %02x%02x%02x%02x %02x%02x%02x%02x "
             "%02x%02x%02x%02x %02x%02x%02x%02x\n"
-- 
GitLab


From 770479fb0fd558a7319bcf15d693e887622d6dc9 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Mon, 3 Feb 2025 23:54:00 +0300
Subject: [PATCH 10/41] small fixes x4

---
 source/ak_belt_hash.c | 15 +--------------
 source/libakrypt.h    |  2 --
 2 files changed, 1 insertion(+), 16 deletions(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index a1d596a..87320d6 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -301,17 +301,6 @@ ak_uint32 u32Rev(ak_uint32 w) {
   ((ak_uint32*)(block))[2] = u32Rev(((ak_uint32*)(block))[2]),\
   ((ak_uint32*)(block))[3] = u32Rev(((ak_uint32*)(block))[3])
 
-// size_t beltHash_keep()
-// {
-//  return sizeof(belt_hash_st)/* + 12*4*/;
-// }
-
-
-
-
-
-
-
  static int ak_hash_context_belt_hash_clean( ak_pointer bctx )
 {
   ak_belt_hash cx = ( ak_belt_hash ) bctx;
@@ -321,8 +310,6 @@ ak_uint32 u32Rev(ak_uint32 w) {
   beltBlockSetZero(cx->ls + 4);
   // h <- B194...0D
   memmove(cx->h, beltH(), 32);
-  // нет накопленнных данных
-  cx->filled = 0;
 
  return ak_error_ok;
 }
@@ -417,7 +404,7 @@ ak_uint32 u32Rev(ak_uint32 w) {
   if(( hctx->oid = ak_oid_find_by_name( "belt-hash" )) == NULL )
     return ak_error_message( ak_error_wrong_oid, __func__,
                                            "incorrect internal search of belt-hash identifier" );
-  if(( error = ak_mac_create( &hctx->mctx, 32, &hctx->data.sctx,
+  if(( error = ak_mac_create( &hctx->mctx, 32, &hctx->data.bctx,
                                              ak_hash_context_belt_hash_clean,
                                              ak_hash_context_belt_hash_update,
                                              ak_hash_context_belt_hash_finalize )) != ak_error_ok )
diff --git a/source/libakrypt.h b/source/libakrypt.h
index d099e01..7d7c80c 100644
--- a/source/libakrypt.h
+++ b/source/libakrypt.h
@@ -891,8 +891,6 @@ extern "C" {
   ak_uint32 h[8];
   /*! \brief Блок данных для шифрования */
   ak_uint8 block[32];
-  /*! \brief Оставшиеся октеты в блоке */
-  size_t filled;
   /*! \brief Стек для работы beltCompr [12*4 байт] */
   ak_uint8 stack[12*4];
 } *ak_belt_hash;
-- 
GitLab


From 7ebfb54b0abf881fc30923ad6953c457d4838f6a Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Tue, 4 Feb 2025 00:00:12 +0300
Subject: [PATCH 11/41] testing consts

---
 examples/tests/test-belt-hash.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/examples/tests/test-belt-hash.c b/examples/tests/test-belt-hash.c
index b4cb248..08be39a 100644
--- a/examples/tests/test-belt-hash.c
+++ b/examples/tests/test-belt-hash.c
@@ -7,7 +7,7 @@
   0x##i, 0x##j, 0x##k, 0x##l, 0x##m, 0x##n, 0x##o, 0x##p
 
 int main( void ) {
-  const ak_uint8 X1[13] = { 
+  ak_uint8 X1[13] = { 
     0xB1, 0x94, 0xBA, 0xC8, 0x0A, 0x08, 0xF5, 0x3B,
     0x36, 0x6D, 0x00, 0x8E, 0x58
   };
@@ -15,7 +15,7 @@ int main( void ) {
     H16(AB,EF,97,25,D4,C5,A8,35,97,A3,67,D1,44,94,CC,25),
     H16(42,F2,0F,65,9D,DF,EC,C9,61,A3,EC,55,0C,BA,8C,75)
   };
-  const ak_uint8 X2[32] = { 
+  ak_uint8 X2[32] = { 
     H16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4),
     H16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D)
   };
@@ -23,7 +23,7 @@ int main( void ) {
     H16(74,9E,4C,36,53,AE,CE,5E,48,DB,47,61,22,77,42,EB),
     H16(6D,BE,13,F4,A8,0F,7B,EF,F1,A9,CF,8D,10,EE,77,86)
   };
-  const ak_uint8 X3[48] = { 
+  ak_uint8 X3[48] = { 
     H16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4),
     H16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D),
     H16(5B,E3,D6,12,17,B9,61,81,FE,67,86,AD,71,6B,89,0B)
-- 
GitLab


From aadaa28185e7c24aa213e10432b9c68f0b60e961 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Tue, 4 Feb 2025 00:24:45 +0300
Subject: [PATCH 12/41] small fixes x5

---
 source/ak_belt_hash.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index 87320d6..1bd60ec 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -368,7 +368,7 @@ ak_uint32 u32Rev(ak_uint32 w) {
                                                                        "input length is too huge" );
   // /* формируем временный текст */
   memset(m, 0, 32);
-  if(dt != NULL)
+  if(in != NULL)
     memcpy(m, dt, ( ak_uint32 )size);
 
   /* при финализации мы изменяем копию существующей структуры */
@@ -378,10 +378,6 @@ ak_uint32 u32Rev(ak_uint32 w) {
   beltBlockRevU32(m + 16);
 #endif
   beltCompress2(bx.ls + 4, bx.h, (ak_uint32*)m, bx.stack);
-#ifndef AK_LITTLE_ENDIAN
-  beltBlockRevU32(m + 16);
-  beltBlockRevU32(m);
-#endif
   beltCompress(bx.h, bx.ls, bx.stack);
   // ak_hash_context_streebog_g( &sx, sx.n, m );
   // ak_hash_context_streebog_add( &sx, size << 3 );
-- 
GitLab


From 862f51c78e72b929e5d82c7b126459fc72a43784 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Tue, 4 Feb 2025 15:47:42 +0300
Subject: [PATCH 13/41] keep on fixes

---
 source/ak_belt_hash.c | 55 +++++++++++++++++++++++++------------------
 source/ak_hash.c      |  5 ++--
 2 files changed, 35 insertions(+), 25 deletions(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index 1bd60ec..30ee30b 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -44,6 +44,7 @@ const ak_uint8* beltH()
 //rotl
 #define ROTL32(a, r) \
   ((ak_uint32)0x##a << r | (ak_uint32)0x##a >> (32 - r))
+
 #define ROTL32x16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p, r)\
   ROTL32(a, r), ROTL32(b, r), ROTL32(c, r), ROTL32(d, r),\
   ROTL32(e, r), ROTL32(f, r), ROTL32(g, r), ROTL32(h, r),\
@@ -172,8 +173,7 @@ static const ak_uint32 H29[256] = {
  * \param block [4*32 бит] Указатель на шифруемый блок данных.
  * \param key [8*32 бит] Указатель на ключ шифрования.
  */
-void beltBlockEncr2(ak_uint32 block[4], const ak_uint32 key[8])
-{
+void beltBlockEncr2(ak_uint32 block[4], const ak_uint32 key[8]) {
   E((block + 0), (block + 1), (block + 2), (block + 3), key);
 }
 
@@ -215,8 +215,7 @@ void beltBlockEncr2(ak_uint32 block[4], const ak_uint32 key[8])
  * \param X [8*32 бит] Указатель на входное значение первой половины данных X.
  * \param stack [12*32 бит] Указатель на промежуточный буфер работы функции.
  */
-void beltCompress(ak_uint32 h[8], const ak_uint32 X[8], void* stack)
-{
+void beltCompress(ak_uint32 h[8], const ak_uint32 X[8], void* stack) {
   // [12]buf = [4]buf0 || [4]buf1 || [4]buf2
   ak_uint32* buf = (ak_uint32*)stack;
   // буферы не пересекаются?
@@ -251,8 +250,7 @@ void beltCompress(ak_uint32 h[8], const ak_uint32 X[8], void* stack)
  * \param stack [12*32 бит] Указатель на промежуточный буфер работы функции.
  */
 static inline void beltCompress2(ak_uint32 s[4], ak_uint32 h[8],
-                   const ak_uint32 X[8], void* stack)
-{
+                   const ak_uint32 X[8], void* stack) {
   // [12]buf = [4]buf0 || [4]buf1 || [4]buf2
   ak_uint32* buf = (ak_uint32*)stack;
   // буферы не пересекаются?
@@ -301,8 +299,7 @@ ak_uint32 u32Rev(ak_uint32 w) {
   ((ak_uint32*)(block))[2] = u32Rev(((ak_uint32*)(block))[2]),\
   ((ak_uint32*)(block))[3] = u32Rev(((ak_uint32*)(block))[3])
 
- static int ak_hash_context_belt_hash_clean( ak_pointer bctx )
-{
+static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
   ak_belt_hash cx = ( ak_belt_hash ) bctx;
   if( cx == NULL ) return ak_error_null_pointer;
 
@@ -311,12 +308,11 @@ ak_uint32 u32Rev(ak_uint32 w) {
   // h <- B194...0D
   memmove(cx->h, beltH(), 32);
 
- return ak_error_ok;
+  return ak_error_ok;
 }
 
  static int ak_hash_context_belt_hash_update(
-  ak_pointer bctx, const ak_pointer in, const size_t size )
-{
+  ak_pointer bctx, const ak_pointer in, const size_t size ) {
   ak_belt_hash cx = ( ak_belt_hash ) bctx;
   const ak_uint8* dt = (const ak_uint8*) in;
   ak_uint32 count = (ak_uint32) size;
@@ -325,7 +321,8 @@ ak_uint32 u32Rev(ak_uint32 w) {
   if( cx == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
                                                "using null pointer to internal streebog context" );
   if(( !size ) || ( in == NULL )) return ak_error_ok;
-
+  if( size & 0x1F ) return ak_error_message( ak_error_wrong_length, __func__,
+                                      "data length is not a multiple of the length of the block" );
   // обновить длину
   carry = (cx->ls[0] += carry) < carry;
   carry = (cx->ls[1] += carry) < carry;
@@ -357,8 +354,8 @@ ak_uint32 u32Rev(ak_uint32 w) {
 {
   ak_belt_hash cx = ( ak_belt_hash ) bctx;
   const ak_uint8* dt = (const ak_uint8*) in;
-  ak_uint8 m[32];
-  struct belt_hash bx; /* структура для хранения копии текущего состояния контекста */
+  //ak_uint8 m[32];
+  struct belt_hash bx[1]; /* структура для хранения копии текущего состояния контекста */
 
   if( cx == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
                                                "using null pointer to internal streebog context" );
@@ -367,18 +364,30 @@ ak_uint32 u32Rev(ak_uint32 w) {
   if( size >= 32 ) return ak_error_message( ak_error_wrong_length, __func__,
                                                                        "input length is too huge" );
   // /* формируем временный текст */
-  memset(m, 0, 32);
-  if(in != NULL)
-    memcpy(m, dt, ( ak_uint32 )size);
+  //memset(m, 0, 32);
+  //if(in != NULL)
+  //  memcpy(m, dt, ( ak_uint32 )size);
+
+  memcpy( bx, cx, sizeof( struct belt_hash ));
+
+  
 
   /* при финализации мы изменяем копию существующей структуры */
-  memcpy( &bx, cx, sizeof( struct belt_hash ));
+  
+  if(size) {
+    memset(bx->block, 0, 32);
+    if (in != NULL) {
+      memcpy(bx->block, in, size);
+    }
 #ifndef AK_LITTLE_ENDIAN
-  beltBlockRevU32(m);
-  beltBlockRevU32(m + 16);
+    beltBlockRevU32(bx->block);
+    beltBlockRevU32(bx->block + 16);
 #endif
-  beltCompress2(bx.ls + 4, bx.h, (ak_uint32*)m, bx.stack);
-  beltCompress(bx.h, bx.ls, bx.stack);
+    beltCompress2(bx->ls + 4, bx->h, (ak_uint32*)bx->block, bx->stack);
+  }
+
+  beltCompress(bx->h, bx->ls, bx->stack);
+
   // ak_hash_context_streebog_g( &sx, sx.n, m );
   // ak_hash_context_streebog_add( &sx, size << 3 );
   // ak_hash_context_streebog_sadd( &sx, m );
@@ -386,7 +395,7 @@ ak_uint32 u32Rev(ak_uint32 w) {
   // ak_hash_context_streebog_g( &sx, NULL, sx.sigma );
 
  /* копируем нужную часть результирующего массива или выдаем сообщение об ошибке */
-  memcpy(out, bx.h, ak_min(32, out_size));
+  memcpy(out, bx->h, ak_min(32, out_size));
 
  return ak_error_ok;
 }
diff --git a/source/ak_hash.c b/source/ak_hash.c
index 82bcd0a..e813114 100644
--- a/source/ak_hash.c
+++ b/source/ak_hash.c
@@ -1512,8 +1512,9 @@
   if( hctx == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
                                                        "destroying null pointer to hash context" );
   hctx->oid = NULL;
-  memset( &hctx->data.sctx, 0, sizeof( struct streebog ));
-  memset( &hctx->data.bctx, 0, sizeof( struct belt_hash ));
+  memset( &hctx->data.sctx, 0,
+    ak_max(sizeof( struct streebog ), sizeof( struct belt_hash ));
+  // memset( &hctx->data.bctx, 0, sizeof( struct belt_hash ));
   if( ak_mac_destroy( &hctx->mctx ) != ak_error_ok )
     ak_error_message( ak_error_get_value(), __func__,
                                                     "incorrect cleaning of internal mac context" );
-- 
GitLab


From a6ed0385abc705b751a6460e2d63d9526477ac22 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Tue, 4 Feb 2025 15:59:16 +0300
Subject: [PATCH 14/41] bug + r fix

---
 source/ak_belt_hash.c | 11 +++++++----
 source/ak_hash.c      |  2 +-
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index 30ee30b..ccd3fab 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -356,6 +356,7 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
   const ak_uint8* dt = (const ak_uint8*) in;
   //ak_uint8 m[32];
   struct belt_hash bx[1]; /* структура для хранения копии текущего состояния контекста */
+  ak_uint32 carry = size << 3;
 
   if( cx == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
                                                "using null pointer to internal streebog context" );
@@ -363,10 +364,12 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
                                                    "using null pointer to externl result buffer" );
   if( size >= 32 ) return ak_error_message( ak_error_wrong_length, __func__,
                                                                        "input length is too huge" );
-  // /* формируем временный текст */
-  //memset(m, 0, 32);
-  //if(in != NULL)
-  //  memcpy(m, dt, ( ak_uint32 )size);
+  
+  // обновить длину
+  carry = (cx->ls[0] += carry) < carry;
+  carry = (cx->ls[1] += carry) < carry;
+  carry = (cx->ls[2] += carry) < carry;
+  cx->ls[3] += carry;
 
   memcpy( bx, cx, sizeof( struct belt_hash ));
 
diff --git a/source/ak_hash.c b/source/ak_hash.c
index e813114..f489703 100644
--- a/source/ak_hash.c
+++ b/source/ak_hash.c
@@ -1513,7 +1513,7 @@
                                                        "destroying null pointer to hash context" );
   hctx->oid = NULL;
   memset( &hctx->data.sctx, 0,
-    ak_max(sizeof( struct streebog ), sizeof( struct belt_hash ));
+    ak_max(sizeof( struct streebog ), sizeof( struct belt_hash )));
   // memset( &hctx->data.bctx, 0, sizeof( struct belt_hash ));
   if( ak_mac_destroy( &hctx->mctx ) != ak_error_ok )
     ak_error_message( ak_error_get_value(), __func__,
-- 
GitLab


From f01d6a9b343775fdf0ae4020ccec9c52f538f6eb Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Tue, 4 Feb 2025 16:21:46 +0300
Subject: [PATCH 15/41] hello printing

---
 source/ak_belt_hash.c | 38 ++++++++++++++++++++++++++++++--------
 1 file changed, 30 insertions(+), 8 deletions(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index ccd3fab..3e0cacf 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -6,6 +6,7 @@
 /* ----------------------------------------------------------------------------------------------- */
 
 #include <libakrypt-internal.h>
+#include <stdio.h> //)))
 
 //---------------------------------------------------------
 //----------------------belt-block-------------------------
@@ -323,12 +324,20 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
   if(( !size ) || ( in == NULL )) return ak_error_ok;
   if( size & 0x1F ) return ak_error_message( ak_error_wrong_length, __func__,
                                       "data length is not a multiple of the length of the block" );
+  
+  printf("\n1: %s\n   %i\n   %s\n",
+    ak_ptr_to_hexstr(cx->h, sizeof(cx->h), ak_false),
+    size,
+    ak_ptr_to_hexstr(in, size, ak_false));
+
   // обновить длину
   carry = (cx->ls[0] += carry) < carry;
   carry = (cx->ls[1] += carry) < carry;
   carry = (cx->ls[2] += carry) < carry;
   cx->ls[3] += carry;
 
+  printf("\n2: %i\n", cx->ls[0]);
+
   // накопленных данных на этот момент не предполагается,
   // потому сразу в цикл по блокам
   // цикл по полным блокам
@@ -345,6 +354,8 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
     count -= 32;
   }
 
+  printf("\n3: %i\n", count);
+
   return ak_error_ok;
 }
 
@@ -353,7 +364,7 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
   const size_t out_size )
 {
   ak_belt_hash cx = ( ak_belt_hash ) bctx;
-  const ak_uint8* dt = (const ak_uint8*) in;
+  //const ak_uint8* dt = (const ak_uint8*) in;
   //ak_uint8 m[32];
   struct belt_hash bx[1]; /* структура для хранения копии текущего состояния контекста */
   ak_uint32 carry = size << 3;
@@ -365,15 +376,20 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
   if( size >= 32 ) return ak_error_message( ak_error_wrong_length, __func__,
                                                                        "input length is too huge" );
   
-  // обновить длину
-  carry = (cx->ls[0] += carry) < carry;
-  carry = (cx->ls[1] += carry) < carry;
-  carry = (cx->ls[2] += carry) < carry;
-  cx->ls[3] += carry;
-
   memcpy( bx, cx, sizeof( struct belt_hash ));
 
-  
+  printf("\n4: %s\n   %i\n   %s\n",
+    ak_ptr_to_hexstr(bx->h, sizeof(bx->h), ak_false),
+    size,
+    ak_ptr_to_hexstr(in, size, ak_false));
+
+  // обновить длину
+  carry = (bx->ls[0] += carry) < carry;
+  carry = (bx->ls[1] += carry) < carry;
+  carry = (bx->ls[2] += carry) < carry;
+  bx->ls[3] += carry;
+
+  printf("\n5: %i\n", bx->ls[0]);
 
   /* при финализации мы изменяем копию существующей структуры */
   
@@ -389,8 +405,14 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
     beltCompress2(bx->ls + 4, bx->h, (ak_uint32*)bx->block, bx->stack);
   }
 
+  printf("\n6: %s\n",
+    ak_ptr_to_hexstr(bx->block, 32, ak_false));
+
   beltCompress(bx->h, bx->ls, bx->stack);
 
+  printf("\n7: %s\n",
+    ak_ptr_to_hexstr(bx->h, 32, ak_false));
+
   // ak_hash_context_streebog_g( &sx, sx.n, m );
   // ak_hash_context_streebog_add( &sx, size << 3 );
   // ak_hash_context_streebog_sadd( &sx, m );
-- 
GitLab


From e2eca242b7c717394f6e85fd673b71c84f75f5ce Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Tue, 4 Feb 2025 16:40:47 +0300
Subject: [PATCH 16/41] something came up

---
 source/ak_belt_hash.c | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index 3e0cacf..4664e5b 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -324,11 +324,6 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
   if(( !size ) || ( in == NULL )) return ak_error_ok;
   if( size & 0x1F ) return ak_error_message( ak_error_wrong_length, __func__,
                                       "data length is not a multiple of the length of the block" );
-  
-  printf("\n1: %s\n   %i\n   %s\n",
-    ak_ptr_to_hexstr(cx->h, sizeof(cx->h), ak_false),
-    size,
-    ak_ptr_to_hexstr(in, size, ak_false));
 
   // обновить длину
   carry = (cx->ls[0] += carry) < carry;
@@ -336,8 +331,6 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
   carry = (cx->ls[2] += carry) < carry;
   cx->ls[3] += carry;
 
-  printf("\n2: %i\n", cx->ls[0]);
-
   // накопленных данных на этот момент не предполагается,
   // потому сразу в цикл по блокам
   // цикл по полным блокам
@@ -354,8 +347,6 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
     count -= 32;
   }
 
-  printf("\n3: %i\n", count);
-
   return ak_error_ok;
 }
 
@@ -398,6 +389,9 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
     if (in != NULL) {
       memcpy(bx->block, in, size);
     }
+
+    printf("\n6: %s\n",
+      ak_ptr_to_hexstr(bx->block, 32, ak_false));
 #ifndef AK_LITTLE_ENDIAN
     beltBlockRevU32(bx->block);
     beltBlockRevU32(bx->block + 16);
@@ -405,9 +399,6 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
     beltCompress2(bx->ls + 4, bx->h, (ak_uint32*)bx->block, bx->stack);
   }
 
-  printf("\n6: %s\n",
-    ak_ptr_to_hexstr(bx->block, 32, ak_false));
-
   beltCompress(bx->h, bx->ls, bx->stack);
 
   printf("\n7: %s\n",
-- 
GitLab


From 33e00787aef5105f5dcf31be7ca5744f7e34421f Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Tue, 4 Feb 2025 16:55:42 +0300
Subject: [PATCH 17/41] strange in pointer

---
 source/ak_belt_hash.c | 22 ++++------------------
 1 file changed, 4 insertions(+), 18 deletions(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index 4664e5b..1c49d03 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -331,9 +331,6 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
   carry = (cx->ls[2] += carry) < carry;
   cx->ls[3] += carry;
 
-  // накопленных данных на этот момент не предполагается,
-  // потому сразу в цикл по блокам
-  // цикл по полным блокам
   while (count >= 32)
   {
     beltBlockCopy(cx->block, dt);
@@ -355,8 +352,6 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
   const size_t out_size )
 {
   ak_belt_hash cx = ( ak_belt_hash ) bctx;
-  //const ak_uint8* dt = (const ak_uint8*) in;
-  //ak_uint8 m[32];
   struct belt_hash bx[1]; /* структура для хранения копии текущего состояния контекста */
   ak_uint32 carry = size << 3;
 
@@ -369,9 +364,9 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
   
   memcpy( bx, cx, sizeof( struct belt_hash ));
 
-  printf("\n4: %s\n   %i\n   %s\n",
-    ak_ptr_to_hexstr(bx->h, sizeof(bx->h), ak_false),
-    size,
+  printf("\n4: %s\n",
+    ak_ptr_to_hexstr(bx->h, sizeof(bx->h), ak_false));
+  printf("   %i\n   %s\n", size,
     ak_ptr_to_hexstr(in, size, ak_false));
 
   // обновить длину
@@ -381,17 +376,15 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
   bx->ls[3] += carry;
 
   printf("\n5: %i\n", bx->ls[0]);
-
-  /* при финализации мы изменяем копию существующей структуры */
   
   if(size) {
     memset(bx->block, 0, 32);
     if (in != NULL) {
       memcpy(bx->block, in, size);
     }
-
     printf("\n6: %s\n",
       ak_ptr_to_hexstr(bx->block, 32, ak_false));
+
 #ifndef AK_LITTLE_ENDIAN
     beltBlockRevU32(bx->block);
     beltBlockRevU32(bx->block + 16);
@@ -404,13 +397,6 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
   printf("\n7: %s\n",
     ak_ptr_to_hexstr(bx->h, 32, ak_false));
 
-  // ak_hash_context_streebog_g( &sx, sx.n, m );
-  // ak_hash_context_streebog_add( &sx, size << 3 );
-  // ak_hash_context_streebog_sadd( &sx, m );
-  // ak_hash_context_streebog_g( &sx, NULL, sx.n );
-  // ak_hash_context_streebog_g( &sx, NULL, sx.sigma );
-
- /* копируем нужную часть результирующего массива или выдаем сообщение об ошибке */
   memcpy(out, bx->h, ak_min(32, out_size));
 
  return ak_error_ok;
-- 
GitLab


From b00f246480a3b0d315ab2a30bcf0e8baf5c77672 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Wed, 5 Feb 2025 15:11:35 +0300
Subject: [PATCH 18/41] looking up

---
 examples/tests/test-belt-hash.c |  6 ------
 source/ak_belt_hash.c           | 22 +++++++++-------------
 2 files changed, 9 insertions(+), 19 deletions(-)

diff --git a/examples/tests/test-belt-hash.c b/examples/tests/test-belt-hash.c
index 08be39a..a21ce16 100644
--- a/examples/tests/test-belt-hash.c
+++ b/examples/tests/test-belt-hash.c
@@ -74,11 +74,9 @@ int main( void ) {
   if(strncmp(A, Y1, 32) == 0) {
     printf("Test 1 was successful\n\n");
     success += 1;
-    //return 0;
   }
   else {
     printf("Test 1 failed\n\n");
-    //return 1;
   }
 
   printf("               -----------Test 2------------\n"
@@ -118,11 +116,9 @@ int main( void ) {
   if(strncmp(A, Y2, 32) == 0) {
     printf("Test 2 was successful\n\n");
     success += 2;
-    //return 0;
   }
   else {
     printf("Test 2 failed\n\n");
-    //return 1;
   }
 
   printf("               -----------Test 3------------\n"
@@ -168,11 +164,9 @@ int main( void ) {
   if(strncmp(A, Y3, 32) == 0) {
     printf("Test 3, was successful\n");
     success += 4;
-    //return 0;
   }
   else {
     printf("Test 3 failed\n");
-    //return 1;
   }
 
   if(success == 7) {
diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index 1c49d03..fae31b6 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -325,12 +325,19 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
   if( size & 0x1F ) return ak_error_message( ak_error_wrong_length, __func__,
                                       "data length is not a multiple of the length of the block" );
 
+  printf("\n1: %s\n   %i\n   %s\n",
+    ak_ptr_to_hexstr(cx->h, sizeof(cx->h), ak_false),
+    size,
+    ak_ptr_to_hexstr(in, size, ak_false));
+
   // обновить длину
   carry = (cx->ls[0] += carry) < carry;
   carry = (cx->ls[1] += carry) < carry;
   carry = (cx->ls[2] += carry) < carry;
   cx->ls[3] += carry;
 
+  printf("\n2: %i\n", cx->ls[0]);
+
   while (count >= 32)
   {
     beltBlockCopy(cx->block, dt);
@@ -347,7 +354,7 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
   return ak_error_ok;
 }
 
- static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
+static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
   const ak_pointer in, const size_t size, ak_pointer out,
   const size_t out_size )
 {
@@ -402,7 +409,7 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
  return ak_error_ok;
 }
 
- int ak_hash_create_belt_hash( ak_hash hctx )
+int ak_hash_create_belt_hash( ak_hash hctx )
 {
   int error = ak_error_ok;
 
@@ -417,16 +424,5 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
                                              ak_hash_context_belt_hash_finalize )) != ak_error_ok )
     return ak_error_message( error, __func__, "incorrect initialization of internal mac context" );
 
- // /* добавочная проверка корректной работы алгоритма хэширования */
- //  if( ak_libakrypt_get_option_by_name( "use_additional_algorithm_check_context" ) == ak_true ) {
- //    ak_hash_context_streebog_clean( &hctx->data.sctx );
- //    if(( error = ak_hash_ptr( hctx, streebog_M1_message, 63, out, sizeof( out ))) != ak_error_ok )
- //      return ak_error_message( error, __func__ , "invalid calculation of streebog256 code" );
-
- //    if( ak_ptr_is_equal_with_log( out, streebog256_testM1, sizeof( out )) != ak_true )
- //      return ak_error_message( ak_error_not_equal_data, __func__ ,
- //                                             "the 1st test from GOST R 34.11-2012 is wrong" );
- //  }
-
   return ak_hash_context_belt_hash_clean( &hctx->data.bctx );
 }
-- 
GitLab


From 94d999504037da50ebd3e591024091b1cf2689bd Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Wed, 5 Feb 2025 15:20:56 +0300
Subject: [PATCH 19/41] making strange test

---
 source/ak_belt_hash.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index fae31b6..b47836b 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -328,7 +328,7 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
   printf("\n1: %s\n   %i\n   %s\n",
     ak_ptr_to_hexstr(cx->h, sizeof(cx->h), ak_false),
     size,
-    ak_ptr_to_hexstr(in, size, ak_false));
+    ak_ptr_to_hexstr(in, size+16, ak_false));
 
   // обновить длину
   carry = (cx->ls[0] += carry) < carry;
-- 
GitLab


From 3f8e6a550469cc778786644c18d0082ea1bb7f85 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Wed, 5 Feb 2025 15:24:55 +0300
Subject: [PATCH 20/41] making strange test x2

---
 source/ak_belt_hash.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index b47836b..3626106 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -325,10 +325,11 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
   if( size & 0x1F ) return ak_error_message( ak_error_wrong_length, __func__,
                                       "data length is not a multiple of the length of the block" );
 
+  count += 16
   printf("\n1: %s\n   %i\n   %s\n",
     ak_ptr_to_hexstr(cx->h, sizeof(cx->h), ak_false),
     size,
-    ak_ptr_to_hexstr(in, size+16, ak_false));
+    ak_ptr_to_hexstr(in, count, ak_false));
 
   // обновить длину
   carry = (cx->ls[0] += carry) < carry;
-- 
GitLab


From c8d45a03c94c4f9803685bf3c272165e63055f5b Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Wed, 5 Feb 2025 15:26:14 +0300
Subject: [PATCH 21/41] making strange test x3

---
 source/ak_belt_hash.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index 3626106..e339ee8 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -326,9 +326,11 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
                                       "data length is not a multiple of the length of the block" );
 
   count += 16
-  printf("\n1: %s\n   %i\n   %s\n",
+  printf("\n1: %s\n   %i\n",
     ak_ptr_to_hexstr(cx->h, sizeof(cx->h), ak_false),
-    size,
+    size);
+  printf("   %i\n   %s\n",
+    count,
     ak_ptr_to_hexstr(in, count, ak_false));
 
   // обновить длину
-- 
GitLab


From aafa71df92f54fb3b8c69c87732d894dfcb1e6f3 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Wed, 5 Feb 2025 15:29:08 +0300
Subject: [PATCH 22/41] making strange test x4

---
 source/ak_belt_hash.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index e339ee8..4661b90 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -325,13 +325,14 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
   if( size & 0x1F ) return ak_error_message( ak_error_wrong_length, __func__,
                                       "data length is not a multiple of the length of the block" );
 
-  count += 16
+  count += 16;
   printf("\n1: %s\n   %i\n",
     ak_ptr_to_hexstr(cx->h, sizeof(cx->h), ak_false),
     size);
   printf("   %i\n   %s\n",
     count,
     ak_ptr_to_hexstr(in, count, ak_false));
+  count -= 16;
 
   // обновить длину
   carry = (cx->ls[0] += carry) < carry;
-- 
GitLab


From 1880576cb6f1fb1f110e8e05177d0404aa839059 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Wed, 5 Feb 2025 15:37:52 +0300
Subject: [PATCH 23/41] oh god

---
 examples/tests/test-belt-hash.c |  2 +-
 source/ak_belt_hash.c           | 25 -------------------------
 2 files changed, 1 insertion(+), 26 deletions(-)

diff --git a/examples/tests/test-belt-hash.c b/examples/tests/test-belt-hash.c
index a21ce16..8034bc8 100644
--- a/examples/tests/test-belt-hash.c
+++ b/examples/tests/test-belt-hash.c
@@ -146,7 +146,7 @@ int main( void ) {
     Y3[24], Y3[25], Y3[26], Y3[27], Y3[28], Y3[29], Y3[30], Y3[31]);
 
   ak_hash_create_belt_hash( &ctx );
-  ak_hash_ptr( &ctx, X2, 48, A, 32 );
+  ak_hash_ptr( &ctx, X3, 48, A, 32 );
   ak_hash_destroy( &ctx );
 
   ak_libakrypt_destroy();
diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index 4661b90..e110d5f 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -6,7 +6,6 @@
 /* ----------------------------------------------------------------------------------------------- */
 
 #include <libakrypt-internal.h>
-#include <stdio.h> //)))
 
 //---------------------------------------------------------
 //----------------------belt-block-------------------------
@@ -325,23 +324,12 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
   if( size & 0x1F ) return ak_error_message( ak_error_wrong_length, __func__,
                                       "data length is not a multiple of the length of the block" );
 
-  count += 16;
-  printf("\n1: %s\n   %i\n",
-    ak_ptr_to_hexstr(cx->h, sizeof(cx->h), ak_false),
-    size);
-  printf("   %i\n   %s\n",
-    count,
-    ak_ptr_to_hexstr(in, count, ak_false));
-  count -= 16;
-
   // обновить длину
   carry = (cx->ls[0] += carry) < carry;
   carry = (cx->ls[1] += carry) < carry;
   carry = (cx->ls[2] += carry) < carry;
   cx->ls[3] += carry;
 
-  printf("\n2: %i\n", cx->ls[0]);
-
   while (count >= 32)
   {
     beltBlockCopy(cx->block, dt);
@@ -375,27 +363,17 @@ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
   
   memcpy( bx, cx, sizeof( struct belt_hash ));
 
-  printf("\n4: %s\n",
-    ak_ptr_to_hexstr(bx->h, sizeof(bx->h), ak_false));
-  printf("   %i\n   %s\n", size,
-    ak_ptr_to_hexstr(in, size, ak_false));
-
   // обновить длину
   carry = (bx->ls[0] += carry) < carry;
   carry = (bx->ls[1] += carry) < carry;
   carry = (bx->ls[2] += carry) < carry;
   bx->ls[3] += carry;
 
-  printf("\n5: %i\n", bx->ls[0]);
-  
   if(size) {
     memset(bx->block, 0, 32);
     if (in != NULL) {
       memcpy(bx->block, in, size);
     }
-    printf("\n6: %s\n",
-      ak_ptr_to_hexstr(bx->block, 32, ak_false));
-
 #ifndef AK_LITTLE_ENDIAN
     beltBlockRevU32(bx->block);
     beltBlockRevU32(bx->block + 16);
@@ -405,9 +383,6 @@ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
 
   beltCompress(bx->h, bx->ls, bx->stack);
 
-  printf("\n7: %s\n",
-    ak_ptr_to_hexstr(bx->h, 32, ak_false));
-
   memcpy(out, bx->h, ak_min(32, out_size));
 
  return ak_error_ok;
-- 
GitLab


From 7f4d9680834a9452defb20740af08c845b762930 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Wed, 5 Feb 2025 17:23:47 +0300
Subject: [PATCH 24/41] looking at test

---
 examples/tests/test-belt-hash.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/examples/tests/test-belt-hash.c b/examples/tests/test-belt-hash.c
index 8034bc8..9980f2d 100644
--- a/examples/tests/test-belt-hash.c
+++ b/examples/tests/test-belt-hash.c
@@ -37,8 +37,12 @@ int main( void ) {
   ak_uint8 A[32] = {0};
   struct hash ctx;
 
-  ak_log_set_level( ak_log_none );
-  ak_libakrypt_create( ak_function_log_stderr );
+  //ak_log_set_level( ak_log_none );
+  //ak_libakrypt_create( ak_function_log_stderr );
+  if (ak_libakrypt_create(NULL) != ak_true) {
+    ak_libakrypt_destroy();
+    return EXIT_FAILURE;
+  }
 
   printf("--------------------Testing belt-hash----------------------\n"
     "               -----------Test 1------------\n"
-- 
GitLab


From 79a2978dac71d527deda243ecce4ebc009410f2c Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Wed, 5 Feb 2025 17:48:11 +0300
Subject: [PATCH 25/41] looking at test x2

---
 examples/tests/test-belt-hash.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/examples/tests/test-belt-hash.c b/examples/tests/test-belt-hash.c
index 9980f2d..2689c74 100644
--- a/examples/tests/test-belt-hash.c
+++ b/examples/tests/test-belt-hash.c
@@ -6,7 +6,7 @@
   0x##a, 0x##b, 0x##c, 0x##d, 0x##e, 0x##f, 0x##g, 0x##h,\
   0x##i, 0x##j, 0x##k, 0x##l, 0x##m, 0x##n, 0x##o, 0x##p
 
-int main( void ) {
+int main() {
   ak_uint8 X1[13] = { 
     0xB1, 0x94, 0xBA, 0xC8, 0x0A, 0x08, 0xF5, 0x3B,
     0x36, 0x6D, 0x00, 0x8E, 0x58
-- 
GitLab


From b71c67dc47cd313c59c48219d2928f49fcf65009 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Wed, 5 Feb 2025 17:51:23 +0300
Subject: [PATCH 26/41] like what

---
 examples/tests/test-belt-hash.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/examples/tests/test-belt-hash.c b/examples/tests/test-belt-hash.c
index 2689c74..d33cf52 100644
--- a/examples/tests/test-belt-hash.c
+++ b/examples/tests/test-belt-hash.c
@@ -75,7 +75,7 @@ int main() {
     A[16], A[17], A[18], A[19], A[20], A[21], A[22], A[23],
     A[24], A[25], A[26], A[27], A[28], A[29], A[30], A[31]);
   
-  if(strncmp(A, Y1, 32) == 0) {
+  if(strncmp( (const char*)A, (const char*)Y1, 32) == 0) {
     printf("Test 1 was successful\n\n");
     success += 1;
   }
@@ -117,7 +117,7 @@ int main() {
     A[16], A[17], A[18], A[19], A[20], A[21], A[22], A[23],
     A[24], A[25], A[26], A[27], A[28], A[29], A[30], A[31]);
   
-  if(strncmp(A, Y2, 32) == 0) {
+  if(strncmp((const char*)A, (const char*)Y2, 32) == 0) {
     printf("Test 2 was successful\n\n");
     success += 2;
   }
@@ -165,7 +165,7 @@ int main() {
     A[16], A[17], A[18], A[19], A[20], A[21], A[22], A[23],
     A[24], A[25], A[26], A[27], A[28], A[29], A[30], A[31]);
   
-  if(strncmp(A, Y3, 32) == 0) {
+  if(strncmp((const char*)A, (const char*)Y3, 32) == 0) {
     printf("Test 3, was successful\n");
     success += 4;
   }
-- 
GitLab


From e984e1bc20011f6ccbe9f35c33ccf8935cb78e2b Mon Sep 17 00:00:00 2001
From: tvtur <tvtur@tvtur.tvtur>
Date: Wed, 5 Feb 2025 15:02:04 +0000
Subject: [PATCH 27/41] testing shell

---
 libakrypt.test.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libakrypt.test.sh b/libakrypt.test.sh
index e648a8c..1bdf519 100755
--- a/libakrypt.test.sh
+++ b/libakrypt.test.sh
@@ -15,7 +15,7 @@ do
                 mkdir -p $name.build
                 cd $name.build
 # выполняем настройку
-                cmake -DCMAKE_C_COMPILER=$name -DAK_STATIC_LIB=ON -DAK_EXAMPLES=ON -DAK_TESTS=ON ../../libakrypt-0.x
+                cmake -DCMAKE_C_COMPILER=$name -DAK_STATIC_LIB=ON -DAK_EXAMPLES=ON -DAK_TESTS=ON ../../libakrypt-0-x-belt-hash
 # выполняем сборку
                 make
 # выполняем тестирование
-- 
GitLab


From fbc45eda85a9ebc90675a5595e2e8edeff3306ed Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Wed, 5 Feb 2025 18:42:05 +0300
Subject: [PATCH 28/41] pretify + fixing r counting

---
 examples/tests/test-belt-hash.c |  2 --
 source/ak_belt_hash.c           | 48 ++++++++++++++++++++++++++-------
 2 files changed, 39 insertions(+), 11 deletions(-)

diff --git a/examples/tests/test-belt-hash.c b/examples/tests/test-belt-hash.c
index d33cf52..75fdc1d 100644
--- a/examples/tests/test-belt-hash.c
+++ b/examples/tests/test-belt-hash.c
@@ -37,8 +37,6 @@ int main() {
   ak_uint8 A[32] = {0};
   struct hash ctx;
 
-  //ak_log_set_level( ak_log_none );
-  //ak_libakrypt_create( ak_function_log_stderr );
   if (ak_libakrypt_create(NULL) != ak_true) {
     ak_libakrypt_destroy();
     return EXIT_FAILURE;
diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index e110d5f..cd9e46a 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -132,9 +132,11 @@ static const ak_uint32 H29[256] = {
 #define G5(x)\
   H5[(x) & 255] ^ H13[(x) >> 8 & 255] ^ \
   H21[(x) >> 16 & 255] ^ H29[(x) >> 24]
+
 #define G13(x)\
   H13[(x) & 255] ^ H21[(x) >> 8 & 255] ^ \
   H29[(x) >> 16 & 255] ^ H5[(x) >> 24]
+
 #define G21(x)\
   H21[(x) & 255] ^ H29[(x) >> 8 & 255] ^ \
   H5[(x) >> 16 & 255] ^ H13[(x) >> 24]
@@ -169,7 +171,7 @@ static const ak_uint32 H29[256] = {
   *b ^= *c, *c ^= *b, *b ^= *c;\
 
 /**
- * \brief Алгоритм шифрования belt-block.
+ * \brief Алгоритм зашифрования belt-block.
  * \param block [4*32 бит] Указатель на шифруемый блок данных.
  * \param key [8*32 бит] Указатель на ключ шифрования.
  */
@@ -210,7 +212,7 @@ void beltBlockEncr2(ak_uint32 block[4], const ak_uint32 key[8]) {
   ((ak_uint32*)(dest))[3] = ((const ak_uint32*)(src))[3]
 
 /**
- * \brief Алгоритм сжатия belt-compress без обработки S
+ * \brief Алгоритм сжатия belt-compress <b>без обработки S</b>.
  * \param h [8*32 бит] Указатель на выходное значение Y <b>и второй половины входного значения X</b>.
  * \param X [8*32 бит] Указатель на входное значение первой половины данных X.
  * \param stack [12*32 бит] Указатель на промежуточный буфер работы функции.
@@ -311,12 +313,13 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
   return ak_error_ok;
 }
 
- static int ak_hash_context_belt_hash_update(
-  ak_pointer bctx, const ak_pointer in, const size_t size ) {
+static int ak_hash_context_belt_hash_update(
+    ak_pointer bctx, const ak_pointer in, const size_t size ) {
   ak_belt_hash cx = ( ak_belt_hash ) bctx;
   const ak_uint8* dt = (const ak_uint8*) in;
-  ak_uint32 count = (ak_uint32) size;
-  ak_uint32 carry = count << 3;
+  ak_uint64 count;
+  ak_uint64 count_for_r;
+  ak_uint32* carry;
 
   if( cx == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
                                                "using null pointer to internal streebog context" );
@@ -325,10 +328,24 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
                                       "data length is not a multiple of the length of the block" );
 
   // обновить длину
+    /*
+  count = size;
+  count_for_r = count << 3;
   carry = (cx->ls[0] += carry) < carry;
   carry = (cx->ls[1] += carry) < carry;
   carry = (cx->ls[2] += carry) < carry;
   cx->ls[3] += carry;
+  */
+  count = size;
+  count_for_r = count << 3;
+  carry = &count_for_r
+
+  cx->ls[0] = carry[0];
+  cx->ls[1] = carry[1];
+  count_for_r = count >> 61;
+  cx->ls[2] = carry[0];
+  cx->ls[3] = 0;
+  
 
   while (count >= 32)
   {
@@ -351,8 +368,10 @@ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
   const size_t out_size )
 {
   ak_belt_hash cx = ( ak_belt_hash ) bctx;
-  struct belt_hash bx[1]; /* структура для хранения копии текущего состояния контекста */
-  ak_uint32 carry = size << 3;
+  struct belt_hash bx[1]; //здесь должна изменяться копия, а не оригинал
+  //ak_uint32 carry = size << 3;
+  ak_uint64 count_for_r;
+  ak_uint32* carry;
 
   if( cx == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
                                                "using null pointer to internal streebog context" );
@@ -364,10 +383,21 @@ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
   memcpy( bx, cx, sizeof( struct belt_hash ));
 
   // обновить длину
+
+  //count = size;
+  count_for_r = size << 3;
+  carry = &count_for_r
+
+  carry[0] = (cx->ls[0] += carry[0]) < carry[0];
+  carry[1] = (cx->ls[1] += carry[0] + carry[1]) < carry[1];
+  count_for_r = size >> 61;
+  carry[0] = (cx->ls[2] += carry[0] + carry[1]) < carry[0];
+  cx->ls[3] += carry[0];
+/*
   carry = (bx->ls[0] += carry) < carry;
   carry = (bx->ls[1] += carry) < carry;
   carry = (bx->ls[2] += carry) < carry;
-  bx->ls[3] += carry;
+  bx->ls[3] += carry;*/
 
   if(size) {
     memset(bx->block, 0, 32);
-- 
GitLab


From 2b2865a2de782439acc4286ac9484db2c0c8d569 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Wed, 5 Feb 2025 18:45:53 +0300
Subject: [PATCH 29/41] little fixes

---
 source/ak_belt_hash.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index cd9e46a..47d6954 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -338,7 +338,7 @@ static int ak_hash_context_belt_hash_update(
   */
   count = size;
   count_for_r = count << 3;
-  carry = &count_for_r
+  carry = (ak_uint32*) &count_for_r;
 
   cx->ls[0] = carry[0];
   cx->ls[1] = carry[1];
@@ -386,7 +386,7 @@ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
 
   //count = size;
   count_for_r = size << 3;
-  carry = &count_for_r
+  carry = (ak_uint32*) &count_for_r
 
   carry[0] = (cx->ls[0] += carry[0]) < carry[0];
   carry[1] = (cx->ls[1] += carry[0] + carry[1]) < carry[1];
-- 
GitLab


From 7a8cdd03b7a98cfaf4dcf872d395bc3075be1432 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Wed, 5 Feb 2025 18:46:38 +0300
Subject: [PATCH 30/41] little fixes x2

---
 source/ak_belt_hash.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index 47d6954..4a49bf2 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -386,7 +386,7 @@ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
 
   //count = size;
   count_for_r = size << 3;
-  carry = (ak_uint32*) &count_for_r
+  carry = (ak_uint32*) &count_for_r;
 
   carry[0] = (cx->ls[0] += carry[0]) < carry[0];
   carry[1] = (cx->ls[1] += carry[0] + carry[1]) < carry[1];
-- 
GitLab


From f0e52f8fc0b80713b472b5bc4e35cdc2c5d62b81 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Wed, 5 Feb 2025 18:56:59 +0300
Subject: [PATCH 31/41] little fixes x3

---
 source/ak_belt_hash.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index 4a49bf2..34a5087 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -389,9 +389,14 @@ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
   carry = (ak_uint32*) &count_for_r;
 
   carry[0] = (cx->ls[0] += carry[0]) < carry[0];
-  carry[1] = (cx->ls[1] += carry[0] + carry[1]) < carry[1];
+  carry[0] = ( carry[1] += carry[0]) < carry[0];
+  carry[1] = (cx->ls[1] += carry[1]) < carry[1];
+  carry[0] = (cx->ls[2] += carry[0]) < carry[0];
+  carry[1] = (cx->ls[2] += carry[1]) < carry[1];
+  cx->ls[3] += carry[0] + carry[1];
+
   count_for_r = size >> 61;
-  carry[0] = (cx->ls[2] += carry[0] + carry[1]) < carry[0];
+  carry[0] = (cx->ls[2] += carry[0]) < carry[0];
   cx->ls[3] += carry[0];
 /*
   carry = (bx->ls[0] += carry) < carry;
-- 
GitLab


From 3e52fab106b693d6b171f2fe1ab381ca82b0aef8 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Wed, 5 Feb 2025 19:04:10 +0300
Subject: [PATCH 32/41] printing

---
 source/ak_belt_hash.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index 34a5087..a0e9f95 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -6,6 +6,7 @@
 /* ----------------------------------------------------------------------------------------------- */
 
 #include <libakrypt-internal.h>
+#include <stdio.h>
 
 //---------------------------------------------------------
 //----------------------belt-block-------------------------
@@ -388,15 +389,26 @@ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
   count_for_r = size << 3;
   carry = (ak_uint32*) &count_for_r;
 
+  printf("1: %i %li %i %i\n",
+    cx->ls[0], count_for_r, carry[0], carry[1]);
+
   carry[0] = (cx->ls[0] += carry[0]) < carry[0];
+  printf("2: %i\n", count[0]);
   carry[0] = ( carry[1] += carry[0]) < carry[0];
+  printf("3: %i\n", count[0]);
   carry[1] = (cx->ls[1] += carry[1]) < carry[1];
+  printf("4: %i\n", count[1]);
   carry[0] = (cx->ls[2] += carry[0]) < carry[0];
+  printf("5: %i\n", count[0]);
   carry[1] = (cx->ls[2] += carry[1]) < carry[1];
+  printf("6: %i\n", count[1]);
   cx->ls[3] += carry[0] + carry[1];
 
   count_for_r = size >> 61;
+  printf("7: %i %li %i %i\n",
+    cx->ls[0], count_for_r, carry[0], carry[1]);
   carry[0] = (cx->ls[2] += carry[0]) < carry[0];
+  printf("8: %i\n", count[0]);
   cx->ls[3] += carry[0];
 /*
   carry = (bx->ls[0] += carry) < carry;
-- 
GitLab


From d28131e611f58fdc687b40507bdb6c392ea7a2f3 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Wed, 5 Feb 2025 19:05:29 +0300
Subject: [PATCH 33/41] small fixes

---
 source/ak_belt_hash.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index a0e9f95..b5dbd17 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -393,22 +393,22 @@ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
     cx->ls[0], count_for_r, carry[0], carry[1]);
 
   carry[0] = (cx->ls[0] += carry[0]) < carry[0];
-  printf("2: %i\n", count[0]);
+  printf("2: %i\n", carry[0]);
   carry[0] = ( carry[1] += carry[0]) < carry[0];
-  printf("3: %i\n", count[0]);
+  printf("3: %i\n", carry[0]);
   carry[1] = (cx->ls[1] += carry[1]) < carry[1];
-  printf("4: %i\n", count[1]);
+  printf("4: %i\n", carry[1]);
   carry[0] = (cx->ls[2] += carry[0]) < carry[0];
-  printf("5: %i\n", count[0]);
+  printf("5: %i\n", carry[0]);
   carry[1] = (cx->ls[2] += carry[1]) < carry[1];
-  printf("6: %i\n", count[1]);
+  printf("6: %i\n", carry[1]);
   cx->ls[3] += carry[0] + carry[1];
 
   count_for_r = size >> 61;
   printf("7: %i %li %i %i\n",
     cx->ls[0], count_for_r, carry[0], carry[1]);
   carry[0] = (cx->ls[2] += carry[0]) < carry[0];
-  printf("8: %i\n", count[0]);
+  printf("8: %i\n", carry[0]);
   cx->ls[3] += carry[0];
 /*
   carry = (bx->ls[0] += carry) < carry;
-- 
GitLab


From de7dbefc7abf81a3a3a845ce05d46a64a553bb39 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Wed, 5 Feb 2025 19:09:01 +0300
Subject: [PATCH 34/41] small fixes x2

---
 source/ak_belt_hash.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index b5dbd17..4bd4b53 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -410,6 +410,8 @@ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
   carry[0] = (cx->ls[2] += carry[0]) < carry[0];
   printf("8: %i\n", carry[0]);
   cx->ls[3] += carry[0];
+  printf("7: %i %i %i %i\n",
+    cx->ls[0], cx->ls[1], cx->ls[2], cx->ls[3]);
 /*
   carry = (bx->ls[0] += carry) < carry;
   carry = (bx->ls[1] += carry) < carry;
-- 
GitLab


From 99bb51a33f877a2de288235da8283c09e7d760a6 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Wed, 5 Feb 2025 19:13:18 +0300
Subject: [PATCH 35/41] small fixes x2

---
 source/ak_belt_hash.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index 4bd4b53..708d707 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -392,6 +392,20 @@ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
   printf("1: %i %li %i %i\n",
     cx->ls[0], count_for_r, carry[0], carry[1]);
 
+  carry[0] = (cx->ls[0] += carry[0]) < carry[0];
+  carry[0] = (cx->ls[1] += carry[0]) < carry[0];
+  carry[0] = (cx->ls[2] += carry[0]) < carry[0];
+  cx->ls[3] += carry[0];
+
+  carry[1] = (cx->ls[1] += carry[1]) < carry[1];
+  carry[1] = (cx->ls[2] += carry[1]) < carry[1];
+  cx->ls[3] += carry[1];
+
+  count_for_r = size >> 61;
+  carry[0] = (cx->ls[2] += carry[0]) < carry[0];
+  cx->ls[3] += carry[0];
+
+  /*
   carry[0] = (cx->ls[0] += carry[0]) < carry[0];
   printf("2: %i\n", carry[0]);
   carry[0] = ( carry[1] += carry[0]) < carry[0];
@@ -412,6 +426,7 @@ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
   cx->ls[3] += carry[0];
   printf("7: %i %i %i %i\n",
     cx->ls[0], cx->ls[1], cx->ls[2], cx->ls[3]);
+  */
 /*
   carry = (bx->ls[0] += carry) < carry;
   carry = (bx->ls[1] += carry) < carry;
-- 
GitLab


From 6230b157388c45533939f20f3c90a8162b2e7201 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Wed, 5 Feb 2025 19:17:13 +0300
Subject: [PATCH 36/41] like for real

---
 source/ak_belt_hash.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index 708d707..7d2bdec 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -390,20 +390,20 @@ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
   carry = (ak_uint32*) &count_for_r;
 
   printf("1: %i %li %i %i\n",
-    cx->ls[0], count_for_r, carry[0], carry[1]);
+    bx->ls[0], count_for_r, carry[0], carry[1]);
 
-  carry[0] = (cx->ls[0] += carry[0]) < carry[0];
-  carry[0] = (cx->ls[1] += carry[0]) < carry[0];
-  carry[0] = (cx->ls[2] += carry[0]) < carry[0];
-  cx->ls[3] += carry[0];
+  carry[0] = (bx->ls[0] += carry[0]) < carry[0];
+  carry[0] = (bx->ls[1] += carry[0]) < carry[0];
+  carry[0] = (bx->ls[2] += carry[0]) < carry[0];
+  bx->ls[3] += carry[0];
 
-  carry[1] = (cx->ls[1] += carry[1]) < carry[1];
-  carry[1] = (cx->ls[2] += carry[1]) < carry[1];
-  cx->ls[3] += carry[1];
+  carry[1] = (bx->ls[1] += carry[1]) < carry[1];
+  carry[1] = (bx->ls[2] += carry[1]) < carry[1];
+  bx->ls[3] += carry[1];
 
   count_for_r = size >> 61;
-  carry[0] = (cx->ls[2] += carry[0]) < carry[0];
-  cx->ls[3] += carry[0];
+  carry[0] = (bx->ls[2] += carry[0]) < carry[0];
+  bx->ls[3] += carry[0];
 
   /*
   carry[0] = (cx->ls[0] += carry[0]) < carry[0];
-- 
GitLab


From 75ddf42e8a54701ce6c2b38cef4cdbd99ec8389d Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Wed, 5 Feb 2025 19:18:58 +0300
Subject: [PATCH 37/41] prettify

---
 source/ak_belt_hash.c | 45 +------------------------------------------
 1 file changed, 1 insertion(+), 44 deletions(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index 7d2bdec..2a88cc5 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -6,7 +6,6 @@
 /* ----------------------------------------------------------------------------------------------- */
 
 #include <libakrypt-internal.h>
-#include <stdio.h>
 
 //---------------------------------------------------------
 //----------------------belt-block-------------------------
@@ -329,14 +328,6 @@ static int ak_hash_context_belt_hash_update(
                                       "data length is not a multiple of the length of the block" );
 
   // обновить длину
-    /*
-  count = size;
-  count_for_r = count << 3;
-  carry = (cx->ls[0] += carry) < carry;
-  carry = (cx->ls[1] += carry) < carry;
-  carry = (cx->ls[2] += carry) < carry;
-  cx->ls[3] += carry;
-  */
   count = size;
   count_for_r = count << 3;
   carry = (ak_uint32*) &count_for_r;
@@ -369,8 +360,7 @@ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
   const size_t out_size )
 {
   ak_belt_hash cx = ( ak_belt_hash ) bctx;
-  struct belt_hash bx[1]; //здесь должна изменяться копия, а не оригинал
-  //ak_uint32 carry = size << 3;
+  struct belt_hash bx[1]; //здесь должна изменяться копия контекста, а не оригинал
   ak_uint64 count_for_r;
   ak_uint32* carry;
 
@@ -384,14 +374,9 @@ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
   memcpy( bx, cx, sizeof( struct belt_hash ));
 
   // обновить длину
-
-  //count = size;
   count_for_r = size << 3;
   carry = (ak_uint32*) &count_for_r;
 
-  printf("1: %i %li %i %i\n",
-    bx->ls[0], count_for_r, carry[0], carry[1]);
-
   carry[0] = (bx->ls[0] += carry[0]) < carry[0];
   carry[0] = (bx->ls[1] += carry[0]) < carry[0];
   carry[0] = (bx->ls[2] += carry[0]) < carry[0];
@@ -405,34 +390,6 @@ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
   carry[0] = (bx->ls[2] += carry[0]) < carry[0];
   bx->ls[3] += carry[0];
 
-  /*
-  carry[0] = (cx->ls[0] += carry[0]) < carry[0];
-  printf("2: %i\n", carry[0]);
-  carry[0] = ( carry[1] += carry[0]) < carry[0];
-  printf("3: %i\n", carry[0]);
-  carry[1] = (cx->ls[1] += carry[1]) < carry[1];
-  printf("4: %i\n", carry[1]);
-  carry[0] = (cx->ls[2] += carry[0]) < carry[0];
-  printf("5: %i\n", carry[0]);
-  carry[1] = (cx->ls[2] += carry[1]) < carry[1];
-  printf("6: %i\n", carry[1]);
-  cx->ls[3] += carry[0] + carry[1];
-
-  count_for_r = size >> 61;
-  printf("7: %i %li %i %i\n",
-    cx->ls[0], count_for_r, carry[0], carry[1]);
-  carry[0] = (cx->ls[2] += carry[0]) < carry[0];
-  printf("8: %i\n", carry[0]);
-  cx->ls[3] += carry[0];
-  printf("7: %i %i %i %i\n",
-    cx->ls[0], cx->ls[1], cx->ls[2], cx->ls[3]);
-  */
-/*
-  carry = (bx->ls[0] += carry) < carry;
-  carry = (bx->ls[1] += carry) < carry;
-  carry = (bx->ls[2] += carry) < carry;
-  bx->ls[3] += carry;*/
-
   if(size) {
     memset(bx->block, 0, 32);
     if (in != NULL) {
-- 
GitLab


From ddf6ec4ab2527f28aa08b8b6d4fdff5bef476d5c Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Thu, 6 Feb 2025 18:17:30 +0300
Subject: [PATCH 38/41] exam x1

---
 source/ak_hash.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/source/ak_hash.c b/source/ak_hash.c
index f489703..e706033 100644
--- a/source/ak_hash.c
+++ b/source/ak_hash.c
@@ -1513,7 +1513,8 @@
                                                        "destroying null pointer to hash context" );
   hctx->oid = NULL;
   memset( &hctx->data.sctx, 0,
-    ak_max(sizeof( struct streebog ), sizeof( struct belt_hash )));
+    sizeof (&hctx->data) );
+  //  ak_max(sizeof( struct streebog ), sizeof( struct belt_hash )));
   // memset( &hctx->data.bctx, 0, sizeof( struct belt_hash ));
   if( ak_mac_destroy( &hctx->mctx ) != ak_error_ok )
     ak_error_message( ak_error_get_value(), __func__,
-- 
GitLab


From ee5f8b26ef9d2a7612a2d829cbc1f9ed1a98f3ff Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Fri, 7 Feb 2025 14:13:54 +0300
Subject: [PATCH 39/41] final stitches

---
 source/ak_belt_hash.c | 41 +++++++++++++++--------------------------
 source/ak_hash.c      |  5 +----
 2 files changed, 16 insertions(+), 30 deletions(-)

diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
index 2a88cc5..ab0b3d3 100644
--- a/source/ak_belt_hash.c
+++ b/source/ak_belt_hash.c
@@ -220,8 +220,6 @@ void beltBlockEncr2(ak_uint32 block[4], const ak_uint32 key[8]) {
 void beltCompress(ak_uint32 h[8], const ak_uint32 X[8], void* stack) {
   // [12]buf = [4]buf0 || [4]buf1 || [4]buf2
   ak_uint32* buf = (ak_uint32*)stack;
-  // буферы не пересекаются?
-  //ASSERT(memIsDisjoint3(h, 32, X, 32, buf, 48));
   // buf0, buf1 <- h0 + h1
   beltBlockXor(buf, h, h + 4);
   beltBlockCopy(buf + 4, buf);
@@ -255,8 +253,6 @@ static inline void beltCompress2(ak_uint32 s[4], ak_uint32 h[8],
                    const ak_uint32 X[8], void* stack) {
   // [12]buf = [4]buf0 || [4]buf1 || [4]buf2
   ak_uint32* buf = (ak_uint32*)stack;
-  // буферы не пересекаются?
-  //ASSERT(memIsDisjoint4(s, 16, h, 32, X, 32, buf, 48));
   // buf0, buf1 <- h0 + h1
   beltBlockXor(buf, h, h + 4);
   beltBlockCopy(buf + 4, buf);
@@ -307,7 +303,6 @@ static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
 
   beltBlockSetZero(cx->ls);
   beltBlockSetZero(cx->ls + 4);
-  // h <- B194...0D
   memmove(cx->h, beltH(), 32);
 
   return ak_error_ok;
@@ -361,8 +356,7 @@ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
 {
   ak_belt_hash cx = ( ak_belt_hash ) bctx;
   struct belt_hash bx[1]; //здесь должна изменяться копия контекста, а не оригинал
-  ak_uint64 count_for_r;
-  ak_uint32* carry;
+  ak_uint32 carry;
 
   if( cx == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
                                                "using null pointer to internal streebog context" );
@@ -373,24 +367,15 @@ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
   
   memcpy( bx, cx, sizeof( struct belt_hash ));
 
-  // обновить длину
-  count_for_r = size << 3;
-  carry = (ak_uint32*) &count_for_r;
-
-  carry[0] = (bx->ls[0] += carry[0]) < carry[0];
-  carry[0] = (bx->ls[1] += carry[0]) < carry[0];
-  carry[0] = (bx->ls[2] += carry[0]) < carry[0];
-  bx->ls[3] += carry[0];
-
-  carry[1] = (bx->ls[1] += carry[1]) < carry[1];
-  carry[1] = (bx->ls[2] += carry[1]) < carry[1];
-  bx->ls[3] += carry[1];
-
-  count_for_r = size >> 61;
-  carry[0] = (bx->ls[2] += carry[0]) < carry[0];
-  bx->ls[3] += carry[0];
-
   if(size) {
+    // обновить длину
+    carry = (ak_uint32) size << 3;
+    carry = (bx->ls[0] += carry) < carry;
+    carry = (bx->ls[1] += carry) < carry;
+    carry = (bx->ls[2] += carry) < carry;
+    bx->ls[3] += carry;
+
+    //отработать последний блок
     memset(bx->block, 0, 32);
     if (in != NULL) {
       memcpy(bx->block, in, size);
@@ -401,14 +386,18 @@ static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
 #endif
     beltCompress2(bx->ls + 4, bx->h, (ak_uint32*)bx->block, bx->stack);
   }
-
   beltCompress(bx->h, bx->ls, bx->stack);
 
   memcpy(out, bx->h, ak_min(32, out_size));
 
- return ak_error_ok;
+  return ak_error_ok;
 }
 
+/**
+ * \brief Инициализация контекста функции бесключевого хеширования СТБ 34.101.31-2020 (belt-hash).
+ * \param hctx Контекст функции хеширования, который будет заполнен
+ * \return Функция возвращает код ошибки или \ref ak_error_ok (в случае успеха)
+ */
 int ak_hash_create_belt_hash( ak_hash hctx )
 {
   int error = ak_error_ok;
diff --git a/source/ak_hash.c b/source/ak_hash.c
index e706033..f2060cb 100644
--- a/source/ak_hash.c
+++ b/source/ak_hash.c
@@ -1512,10 +1512,7 @@
   if( hctx == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
                                                        "destroying null pointer to hash context" );
   hctx->oid = NULL;
-  memset( &hctx->data.sctx, 0,
-    sizeof (&hctx->data) );
-  //  ak_max(sizeof( struct streebog ), sizeof( struct belt_hash )));
-  // memset( &hctx->data.bctx, 0, sizeof( struct belt_hash ));
+  memset( &hctx->data.sctx, 0, sizeof (&hctx->data) );
   if( ak_mac_destroy( &hctx->mctx ) != ak_error_ok )
     ak_error_message( ak_error_get_value(), __func__,
                                                     "incorrect cleaning of internal mac context" );
-- 
GitLab


From ebd5a3392276f715b08ec55209ecaf8eb7fee8a4 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Mon, 3 Feb 2025 20:20:12 +0300
Subject: [PATCH 40/41] belt-hash, moved from main, integrated, tested,
 squashed

---
 .gitignore                      |   1 -
 CMakeLists.txt                  |   2 +
 examples/tests/test-belt-hash.c | 178 ++++++++++++++
 libakrypt.test.sh               |   2 +-
 source/ak_belt_hash.c           | 417 ++++++++++++++++++++++++++++++++
 source/ak_hash.c                |   2 +-
 source/ak_oid.c                 |   6 +
 source/libakrypt.h              |  20 +-
 8 files changed, 624 insertions(+), 4 deletions(-)
 create mode 100644 examples/tests/test-belt-hash.c
 create mode 100644 source/ak_belt_hash.c

diff --git a/.gitignore b/.gitignore
index 4b20c12..c10aad4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,4 +6,3 @@ scratch*
 *.kdev4
 tags
 doc/conf.py
-
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3aee7e9..f72f362 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -95,6 +95,7 @@ set( AKRYPT_SOURCES
    source/ak_blom.c
    source/ak_kdf.c
    source/ak_encrypt.c
+   source/ak_belt_hash.c
 )
 
 # -------------------------------------------------------------------------------------------------- #
@@ -336,6 +337,7 @@ set ( ARITHMETIC_TESTS_LIST
       hash02
       kuznechik01
       mac-offset
+      belt-hash
     )
 
 if( AK_TESTS_GMP )
diff --git a/examples/tests/test-belt-hash.c b/examples/tests/test-belt-hash.c
new file mode 100644
index 0000000..75fdc1d
--- /dev/null
+++ b/examples/tests/test-belt-hash.c
@@ -0,0 +1,178 @@
+#include <libakrypt.h>
+#include <string.h>
+
+//подстановка битов
+#define H16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)\
+  0x##a, 0x##b, 0x##c, 0x##d, 0x##e, 0x##f, 0x##g, 0x##h,\
+  0x##i, 0x##j, 0x##k, 0x##l, 0x##m, 0x##n, 0x##o, 0x##p
+
+int main() {
+  ak_uint8 X1[13] = { 
+    0xB1, 0x94, 0xBA, 0xC8, 0x0A, 0x08, 0xF5, 0x3B,
+    0x36, 0x6D, 0x00, 0x8E, 0x58
+  };
+  const ak_uint8 Y1[32] = {
+    H16(AB,EF,97,25,D4,C5,A8,35,97,A3,67,D1,44,94,CC,25),
+    H16(42,F2,0F,65,9D,DF,EC,C9,61,A3,EC,55,0C,BA,8C,75)
+  };
+  ak_uint8 X2[32] = { 
+    H16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4),
+    H16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D)
+  };
+  const ak_uint8 Y2[32] = {
+    H16(74,9E,4C,36,53,AE,CE,5E,48,DB,47,61,22,77,42,EB),
+    H16(6D,BE,13,F4,A8,0F,7B,EF,F1,A9,CF,8D,10,EE,77,86)
+  };
+  ak_uint8 X3[48] = { 
+    H16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4),
+    H16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D),
+    H16(5B,E3,D6,12,17,B9,61,81,FE,67,86,AD,71,6B,89,0B)
+  };
+  const ak_uint8 Y3[32] = {
+    H16(9D,02,EE,44,6F,B6,A2,9F,E5,C9,82,D4,B1,3A,F9,D3),
+    H16(E9,08,61,BC,4C,EF,27,CF,30,6B,FB,0B,17,4A,15,4A)
+  };
+
+  ak_uint8 success = 0;
+  ak_uint8 A[32] = {0};
+  struct hash ctx;
+
+  if (ak_libakrypt_create(NULL) != ak_true) {
+    ak_libakrypt_destroy();
+    return EXIT_FAILURE;
+  }
+
+  printf("--------------------Testing belt-hash----------------------\n"
+    "               -----------Test 1------------\n"
+    "Input:\n"
+    " > X1 = %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x\n"
+    "Expected output:\n"
+    " > Y1 = %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "        %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n",
+    X1[0] , X1[1] , X1[2] , X1[3] , X1[4] , X1[5] , X1[6] , X1[7] ,
+    X1[8] , X1[9] , X1[10], X1[11], X1[12],
+    Y1[0] , Y1[1] , Y1[2] , Y1[3] , Y1[4] , Y1[5] , Y1[6] , Y1[7] ,
+    Y1[8] , Y1[9] , Y1[10], Y1[11], Y1[12], Y1[13], Y1[14], Y1[15],
+    Y1[16], Y1[17], Y1[18], Y1[19], Y1[20], Y1[21], Y1[22], Y1[23],
+    Y1[24], Y1[25], Y1[26], Y1[27], Y1[28], Y1[29], Y1[30], Y1[31]);
+
+  ak_hash_create_belt_hash( &ctx );
+  ak_hash_ptr( &ctx, X1, 13, A, 32 );
+  ak_hash_destroy( &ctx );
+
+  printf("Output:\n"
+    " > Y1 = %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "        %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n",
+    A[0] , A[1] , A[2] , A[3] , A[4] , A[5] , A[6] , A[7] ,
+    A[8] , A[9] , A[10], A[11], A[12], A[13], A[14], A[15],
+    A[16], A[17], A[18], A[19], A[20], A[21], A[22], A[23],
+    A[24], A[25], A[26], A[27], A[28], A[29], A[30], A[31]);
+  
+  if(strncmp( (const char*)A, (const char*)Y1, 32) == 0) {
+    printf("Test 1 was successful\n\n");
+    success += 1;
+  }
+  else {
+    printf("Test 1 failed\n\n");
+  }
+
+  printf("               -----------Test 2------------\n"
+    "Input:\n"
+    " > X2 = %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "        %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "Expected output:\n"
+    " > Y2 = %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "        %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n",
+    X2[0] , X2[1] , X2[2] , X2[3] , X2[4] , X2[5] , X2[6] , X2[7] ,
+    X2[8] , X2[9] , X2[10], X2[11], X2[12], X2[13], X2[14], X2[15],
+    X2[16], X2[17], X2[18], X2[19], X2[20], X2[21], X2[22], X2[23],
+    X2[24], X2[25], X2[26], X2[27], X2[28], X2[29], X2[30], X2[31],
+    Y2[0] , Y2[1] , Y2[2] , Y2[3] , Y2[4] , Y2[5] , Y2[6] , Y2[7] ,
+    Y2[8] , Y2[9] , Y2[10], Y2[11], Y2[12], Y2[13], Y2[14], Y2[15],
+    Y2[16], Y2[17], Y2[18], Y2[19], Y2[20], Y2[21], Y2[22], Y2[23],
+    Y2[24], Y2[25], Y2[26], Y2[27], Y2[28], Y2[29], Y2[30], Y2[31]);
+
+  ak_hash_create_belt_hash( &ctx );
+  ak_hash_ptr( &ctx, X2, 32, A, 32 );
+  ak_hash_destroy( &ctx );
+
+  printf("Output:\n"
+    " > Y2 = %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "        %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n",
+    A[0] , A[1] , A[2] , A[3] , A[4] , A[5] , A[6] , A[7] ,
+    A[8] , A[9] , A[10], A[11], A[12], A[13], A[14], A[15],
+    A[16], A[17], A[18], A[19], A[20], A[21], A[22], A[23],
+    A[24], A[25], A[26], A[27], A[28], A[29], A[30], A[31]);
+  
+  if(strncmp((const char*)A, (const char*)Y2, 32) == 0) {
+    printf("Test 2 was successful\n\n");
+    success += 2;
+  }
+  else {
+    printf("Test 2 failed\n\n");
+  }
+
+  printf("               -----------Test 3------------\n"
+    "Input:\n"
+    " > X3 = %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "        %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "        %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "Expected output:\n"
+    " > Y3 = %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "        %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n",
+    X3[0] , X3[1] , X3[2] , X3[3] , X3[4] , X3[5] , X3[6] , X3[7] ,
+    X3[8] , X3[9] , X3[10], X3[11], X3[12], X3[13], X3[14], X3[15],
+    X3[16], X3[17], X3[18], X3[19], X3[20], X3[21], X3[22], X3[23],
+    X3[24], X3[25], X3[26], X3[27], X3[28], X3[29], X3[30], X3[31],
+    X3[32], X3[33], X3[34], X3[35], X3[36], X3[37], X3[38], X3[39],
+    X3[40], X3[41], X3[42], X3[43], X3[44], X3[45], X3[46], X3[47],
+    Y3[0] , Y3[1] , Y3[2] , Y3[3] , Y3[4] , Y3[5] , Y3[6] , Y3[7] ,
+    Y3[8] , Y3[9] , Y3[10], Y3[11], Y3[12], Y3[13], Y3[14], Y3[15],
+    Y3[16], Y3[17], Y3[18], Y3[19], Y3[20], Y3[21], Y3[22], Y3[23],
+    Y3[24], Y3[25], Y3[26], Y3[27], Y3[28], Y3[29], Y3[30], Y3[31]);
+
+  ak_hash_create_belt_hash( &ctx );
+  ak_hash_ptr( &ctx, X3, 48, A, 32 );
+  ak_hash_destroy( &ctx );
+
+  ak_libakrypt_destroy();
+
+  printf("Output:\n"
+    " > Y3 = %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n"
+    "        %02x%02x%02x%02x %02x%02x%02x%02x "
+            "%02x%02x%02x%02x %02x%02x%02x%02x\n",
+    A[0] , A[1] , A[2] , A[3] , A[4] , A[5] , A[6] , A[7] ,
+    A[8] , A[9] , A[10], A[11], A[12], A[13], A[14], A[15],
+    A[16], A[17], A[18], A[19], A[20], A[21], A[22], A[23],
+    A[24], A[25], A[26], A[27], A[28], A[29], A[30], A[31]);
+  
+  if(strncmp((const char*)A, (const char*)Y3, 32) == 0) {
+    printf("Test 3, was successful\n");
+    success += 4;
+  }
+  else {
+    printf("Test 3 failed\n");
+  }
+
+  if(success == 7) {
+    return EXIT_SUCCESS;
+  }
+  return EXIT_FAILURE;
+}
diff --git a/libakrypt.test.sh b/libakrypt.test.sh
index e648a8c..1bdf519 100755
--- a/libakrypt.test.sh
+++ b/libakrypt.test.sh
@@ -15,7 +15,7 @@ do
                 mkdir -p $name.build
                 cd $name.build
 # выполняем настройку
-                cmake -DCMAKE_C_COMPILER=$name -DAK_STATIC_LIB=ON -DAK_EXAMPLES=ON -DAK_TESTS=ON ../../libakrypt-0.x
+                cmake -DCMAKE_C_COMPILER=$name -DAK_STATIC_LIB=ON -DAK_EXAMPLES=ON -DAK_TESTS=ON ../../libakrypt-0-x-belt-hash
 # выполняем сборку
                 make
 # выполняем тестирование
diff --git a/source/ak_belt_hash.c b/source/ak_belt_hash.c
new file mode 100644
index 0000000..ab0b3d3
--- /dev/null
+++ b/source/ak_belt_hash.c
@@ -0,0 +1,417 @@
+/* ----------------------------------------------------------------------------------------------- */
+/*                                                                                                 */
+/*  Реализация хэширования сообщения                                                               */
+/*  из Белорусского стандарта СТБ 34.101.31-2020                                                   */
+/*                                                                                                 */
+/* ----------------------------------------------------------------------------------------------- */
+
+#include <libakrypt-internal.h>
+
+//---------------------------------------------------------
+//----------------------belt-block-------------------------
+//---------------------------------------------------------
+
+//подстановка битов
+#define H16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)\
+  0x##a, 0x##b, 0x##c, 0x##d, 0x##e, 0x##f, 0x##g, 0x##h,\
+  0x##i, 0x##j, 0x##k, 0x##l, 0x##m, 0x##n, 0x##o, 0x##p
+
+//базовая H
+static const ak_uint8 H[256] = {
+  H16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4),
+  H16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D),
+  H16(5B,E3,D6,12,17,B9,61,81,FE,67,86,AD,71,6B,89,0B),
+  H16(5C,B0,C0,FF,33,C3,56,B8,35,C4,05,AE,D8,E0,7F,99),
+  H16(E1,2B,DC,1A,E2,82,57,EC,70,3F,CC,F0,95,EE,8D,F1),
+  H16(C1,AB,76,38,9F,E6,78,CA,F7,C6,F8,60,D5,BB,9C,4F),
+  H16(F3,3C,65,7B,63,7C,30,6A,DD,4E,A7,79,9E,B2,3D,31),
+  H16(3E,98,B5,6E,27,D3,BC,CF,59,1E,18,1F,4C,5A,B7,93),
+  H16(E9,DE,E7,2C,8F,0C,0F,A6,2D,DB,49,F4,6F,73,96,47),
+  H16(06,07,53,16,ED,24,7A,37,39,CB,A3,83,03,A9,8B,F6),
+  H16(92,BD,9B,1C,E5,D1,41,01,54,45,FB,C9,5E,4D,0E,F2),
+  H16(68,20,80,AA,22,7D,64,2F,26,87,F9,34,90,40,55,11),
+  H16(BE,32,97,13,43,FC,9A,48,A0,2A,88,5F,19,4B,09,A1),
+  H16(7E,CD,A4,D0,15,44,AF,8C,A5,84,50,BF,66,D2,E8,8A),
+  H16(A2,D7,46,52,42,A8,DF,B3,69,74,C5,51,EB,23,29,21),
+  H16(D4,EF,D9,B4,3A,62,28,75,91,14,10,EA,77,6C,DA,1D),
+};
+
+const ak_uint8* beltH()
+{
+  return H;
+}
+
+//rotl
+#define ROTL32(a, r) \
+  ((ak_uint32)0x##a << r | (ak_uint32)0x##a >> (32 - r))
+
+#define ROTL32x16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p, r)\
+  ROTL32(a, r), ROTL32(b, r), ROTL32(c, r), ROTL32(d, r),\
+  ROTL32(e, r), ROTL32(f, r), ROTL32(g, r), ROTL32(h, r),\
+  ROTL32(i, r), ROTL32(j, r), ROTL32(k, r), ROTL32(l, r),\
+  ROTL32(m, r), ROTL32(n, r), ROTL32(o, r), ROTL32(p, r)
+
+//rotl(h)
+static const ak_uint32 H5[256] = {
+  ROTL32x16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4, 5),
+  ROTL32x16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D, 5),
+  ROTL32x16(5B,E3,D6,12,17,B9,61,81,FE,67,86,AD,71,6B,89,0B, 5),
+  ROTL32x16(5C,B0,C0,FF,33,C3,56,B8,35,C4,05,AE,D8,E0,7F,99, 5),
+  ROTL32x16(E1,2B,DC,1A,E2,82,57,EC,70,3F,CC,F0,95,EE,8D,F1, 5),
+  ROTL32x16(C1,AB,76,38,9F,E6,78,CA,F7,C6,F8,60,D5,BB,9C,4F, 5),
+  ROTL32x16(F3,3C,65,7B,63,7C,30,6A,DD,4E,A7,79,9E,B2,3D,31, 5),
+  ROTL32x16(3E,98,B5,6E,27,D3,BC,CF,59,1E,18,1F,4C,5A,B7,93, 5),
+  ROTL32x16(E9,DE,E7,2C,8F,0C,0F,A6,2D,DB,49,F4,6F,73,96,47, 5),
+  ROTL32x16(06,07,53,16,ED,24,7A,37,39,CB,A3,83,03,A9,8B,F6, 5),
+  ROTL32x16(92,BD,9B,1C,E5,D1,41,01,54,45,FB,C9,5E,4D,0E,F2, 5),
+  ROTL32x16(68,20,80,AA,22,7D,64,2F,26,87,F9,34,90,40,55,11, 5),
+  ROTL32x16(BE,32,97,13,43,FC,9A,48,A0,2A,88,5F,19,4B,09,A1, 5),
+  ROTL32x16(7E,CD,A4,D0,15,44,AF,8C,A5,84,50,BF,66,D2,E8,8A, 5),
+  ROTL32x16(A2,D7,46,52,42,A8,DF,B3,69,74,C5,51,EB,23,29,21, 5),
+  ROTL32x16(D4,EF,D9,B4,3A,62,28,75,91,14,10,EA,77,6C,DA,1D, 5),
+};
+
+static const ak_uint32 H13[256] = {
+  ROTL32x16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4, 13),
+  ROTL32x16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D, 13),
+  ROTL32x16(5B,E3,D6,12,17,B9,61,81,FE,67,86,AD,71,6B,89,0B, 13),
+  ROTL32x16(5C,B0,C0,FF,33,C3,56,B8,35,C4,05,AE,D8,E0,7F,99, 13),
+  ROTL32x16(E1,2B,DC,1A,E2,82,57,EC,70,3F,CC,F0,95,EE,8D,F1, 13),
+  ROTL32x16(C1,AB,76,38,9F,E6,78,CA,F7,C6,F8,60,D5,BB,9C,4F, 13),
+  ROTL32x16(F3,3C,65,7B,63,7C,30,6A,DD,4E,A7,79,9E,B2,3D,31, 13),
+  ROTL32x16(3E,98,B5,6E,27,D3,BC,CF,59,1E,18,1F,4C,5A,B7,93, 13),
+  ROTL32x16(E9,DE,E7,2C,8F,0C,0F,A6,2D,DB,49,F4,6F,73,96,47, 13),
+  ROTL32x16(06,07,53,16,ED,24,7A,37,39,CB,A3,83,03,A9,8B,F6, 13),
+  ROTL32x16(92,BD,9B,1C,E5,D1,41,01,54,45,FB,C9,5E,4D,0E,F2, 13),
+  ROTL32x16(68,20,80,AA,22,7D,64,2F,26,87,F9,34,90,40,55,11, 13),
+  ROTL32x16(BE,32,97,13,43,FC,9A,48,A0,2A,88,5F,19,4B,09,A1, 13),
+  ROTL32x16(7E,CD,A4,D0,15,44,AF,8C,A5,84,50,BF,66,D2,E8,8A, 13),
+  ROTL32x16(A2,D7,46,52,42,A8,DF,B3,69,74,C5,51,EB,23,29,21, 13),
+  ROTL32x16(D4,EF,D9,B4,3A,62,28,75,91,14,10,EA,77,6C,DA,1D, 13),
+};
+
+static const ak_uint32 H21[256] = {
+  ROTL32x16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4, 21),
+  ROTL32x16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D, 21),
+  ROTL32x16(5B,E3,D6,12,17,B9,61,81,FE,67,86,AD,71,6B,89,0B, 21),
+  ROTL32x16(5C,B0,C0,FF,33,C3,56,B8,35,C4,05,AE,D8,E0,7F,99, 21),
+  ROTL32x16(E1,2B,DC,1A,E2,82,57,EC,70,3F,CC,F0,95,EE,8D,F1, 21),
+  ROTL32x16(C1,AB,76,38,9F,E6,78,CA,F7,C6,F8,60,D5,BB,9C,4F, 21),
+  ROTL32x16(F3,3C,65,7B,63,7C,30,6A,DD,4E,A7,79,9E,B2,3D,31, 21),
+  ROTL32x16(3E,98,B5,6E,27,D3,BC,CF,59,1E,18,1F,4C,5A,B7,93, 21),
+  ROTL32x16(E9,DE,E7,2C,8F,0C,0F,A6,2D,DB,49,F4,6F,73,96,47, 21),
+  ROTL32x16(06,07,53,16,ED,24,7A,37,39,CB,A3,83,03,A9,8B,F6, 21),
+  ROTL32x16(92,BD,9B,1C,E5,D1,41,01,54,45,FB,C9,5E,4D,0E,F2, 21),
+  ROTL32x16(68,20,80,AA,22,7D,64,2F,26,87,F9,34,90,40,55,11, 21),
+  ROTL32x16(BE,32,97,13,43,FC,9A,48,A0,2A,88,5F,19,4B,09,A1, 21),
+  ROTL32x16(7E,CD,A4,D0,15,44,AF,8C,A5,84,50,BF,66,D2,E8,8A, 21),
+  ROTL32x16(A2,D7,46,52,42,A8,DF,B3,69,74,C5,51,EB,23,29,21, 21),
+  ROTL32x16(D4,EF,D9,B4,3A,62,28,75,91,14,10,EA,77,6C,DA,1D, 21),
+};
+
+static const ak_uint32 H29[256] = {
+  ROTL32x16(B1,94,BA,C8,0A,08,F5,3B,36,6D,00,8E,58,4A,5D,E4, 29),
+  ROTL32x16(85,04,FA,9D,1B,B6,C7,AC,25,2E,72,C2,02,FD,CE,0D, 29),
+  ROTL32x16(5B,E3,D6,12,17,B9,61,81,FE,67,86,AD,71,6B,89,0B, 29),
+  ROTL32x16(5C,B0,C0,FF,33,C3,56,B8,35,C4,05,AE,D8,E0,7F,99, 29),
+  ROTL32x16(E1,2B,DC,1A,E2,82,57,EC,70,3F,CC,F0,95,EE,8D,F1, 29),
+  ROTL32x16(C1,AB,76,38,9F,E6,78,CA,F7,C6,F8,60,D5,BB,9C,4F, 29),
+  ROTL32x16(F3,3C,65,7B,63,7C,30,6A,DD,4E,A7,79,9E,B2,3D,31, 29),
+  ROTL32x16(3E,98,B5,6E,27,D3,BC,CF,59,1E,18,1F,4C,5A,B7,93, 29),
+  ROTL32x16(E9,DE,E7,2C,8F,0C,0F,A6,2D,DB,49,F4,6F,73,96,47, 29),
+  ROTL32x16(06,07,53,16,ED,24,7A,37,39,CB,A3,83,03,A9,8B,F6, 29),
+  ROTL32x16(92,BD,9B,1C,E5,D1,41,01,54,45,FB,C9,5E,4D,0E,F2, 29),
+  ROTL32x16(68,20,80,AA,22,7D,64,2F,26,87,F9,34,90,40,55,11, 29),
+  ROTL32x16(BE,32,97,13,43,FC,9A,48,A0,2A,88,5F,19,4B,09,A1, 29),
+  ROTL32x16(7E,CD,A4,D0,15,44,AF,8C,A5,84,50,BF,66,D2,E8,8A, 29),
+  ROTL32x16(A2,D7,46,52,42,A8,DF,B3,69,74,C5,51,EB,23,29,21, 29),
+  ROTL32x16(D4,EF,D9,B4,3A,62,28,75,91,14,10,EA,77,6C,DA,1D, 29),
+};
+
+//gr(x)
+#define G5(x)\
+  H5[(x) & 255] ^ H13[(x) >> 8 & 255] ^ \
+  H21[(x) >> 16 & 255] ^ H29[(x) >> 24]
+
+#define G13(x)\
+  H13[(x) & 255] ^ H21[(x) >> 8 & 255] ^ \
+  H29[(x) >> 16 & 255] ^ H5[(x) >> 24]
+
+#define G21(x)\
+  H21[(x) & 255] ^ H29[(x) >> 8 & 255] ^ \
+  H5[(x) >> 16 & 255] ^ H13[(x) >> 24]
+
+//1 раунд
+#define R(a, b, c, d, K, i, subkey)\
+  *b ^= G5(*a + subkey(K, i, 0));\
+  *c ^= G21(*d + subkey(K, i, 1));\
+  *a -= G13(*b + subkey(K, i, 2));\
+  *c += *b;\
+  *b += G21(*c + subkey(K, i, 3)) ^ i;\
+  *c -= *b;\
+  *d += G13(*c + subkey(K, i, 4));\
+  *b ^= G21(*a + subkey(K, i, 5));\
+  *c ^= G5(*d + subkey(K, i, 6));\
+
+//ключевая развертка
+#define subkey_e(K, i, j) K[(7 * (i) - 7 + (j)) % 8]
+
+//зашифрование с перестановкой через аргументы
+#define E(a, b, c, d, K)\
+  R(a, b, c, d, K, 1, subkey_e);\
+  R(b, d, a, c, K, 2, subkey_e);\
+  R(d, c, b, a, K, 3, subkey_e);\
+  R(c, a, d, b, K, 4, subkey_e);\
+  R(a, b, c, d, K, 5, subkey_e);\
+  R(b, d, a, c, K, 6, subkey_e);\
+  R(d, c, b, a, K, 7, subkey_e);\
+  R(c, a, d, b, K, 8, subkey_e);\
+  *a ^= *b, *b ^= *a, *a ^= *b;\
+  *c ^= *d, *d ^= *c, *c ^= *d;\
+  *b ^= *c, *c ^= *b, *b ^= *c;\
+
+/**
+ * \brief Алгоритм зашифрования belt-block.
+ * \param block [4*32 бит] Указатель на шифруемый блок данных.
+ * \param key [8*32 бит] Указатель на ключ шифрования.
+ */
+void beltBlockEncr2(ak_uint32 block[4], const ak_uint32 key[8]) {
+  E((block + 0), (block + 1), (block + 2), (block + 3), key);
+}
+
+//---------------------------------------------------------
+//--------------------belt-compress------------------------
+//---------------------------------------------------------
+
+#define beltBlockNeg(dest, src)\
+  ((ak_uint32*)(dest))[0] = ~((const ak_uint32*)(src))[0],\
+  ((ak_uint32*)(dest))[1] = ~((const ak_uint32*)(src))[1],\
+  ((ak_uint32*)(dest))[2] = ~((const ak_uint32*)(src))[2],\
+  ((ak_uint32*)(dest))[3] = ~((const ak_uint32*)(src))[3]
+
+#define beltBlockXor(dest, src1, src2)\
+  ((ak_uint32*)(dest))[0] = \
+    ((const ak_uint32*)(src1))[0] ^ ((const ak_uint32*)(src2))[0],\
+  ((ak_uint32*)(dest))[1] = \
+    ((const ak_uint32*)(src1))[1] ^ ((const ak_uint32*)(src2))[1],\
+  ((ak_uint32*)(dest))[2] = \
+    ((const ak_uint32*)(src1))[2] ^ ((const ak_uint32*)(src2))[2],\
+  ((ak_uint32*)(dest))[3] = \
+    ((const ak_uint32*)(src1))[3] ^ ((const ak_uint32*)(src2))[3]
+
+#define beltBlockXor2(dest, src)\
+  ((ak_uint32*)(dest))[0] ^= ((const ak_uint32*)(src))[0],\
+  ((ak_uint32*)(dest))[1] ^= ((const ak_uint32*)(src))[1],\
+  ((ak_uint32*)(dest))[2] ^= ((const ak_uint32*)(src))[2],\
+  ((ak_uint32*)(dest))[3] ^= ((const ak_uint32*)(src))[3]
+
+#define beltBlockCopy(dest, src)\
+  ((ak_uint32*)(dest))[0] = ((const ak_uint32*)(src))[0],\
+  ((ak_uint32*)(dest))[1] = ((const ak_uint32*)(src))[1],\
+  ((ak_uint32*)(dest))[2] = ((const ak_uint32*)(src))[2],\
+  ((ak_uint32*)(dest))[3] = ((const ak_uint32*)(src))[3]
+
+/**
+ * \brief Алгоритм сжатия belt-compress <b>без обработки S</b>.
+ * \param h [8*32 бит] Указатель на выходное значение Y <b>и второй половины входного значения X</b>.
+ * \param X [8*32 бит] Указатель на входное значение первой половины данных X.
+ * \param stack [12*32 бит] Указатель на промежуточный буфер работы функции.
+ */
+void beltCompress(ak_uint32 h[8], const ak_uint32 X[8], void* stack) {
+  // [12]buf = [4]buf0 || [4]buf1 || [4]buf2
+  ak_uint32* buf = (ak_uint32*)stack;
+  // buf0, buf1 <- h0 + h1
+  beltBlockXor(buf, h, h + 4);
+  beltBlockCopy(buf + 4, buf);
+  // buf0 <- beltBlock(buf0, X) + buf1
+  beltBlockEncr2(buf, X);
+  beltBlockXor2(buf, buf + 4);
+  // buf2 <- h0
+  beltBlockCopy(buf + 8, h);
+  // buf1 <- h1 [buf01 == K1]
+  beltBlockCopy(buf + 4, h + 4);
+  // h0 <- beltBlock(X0, buf01) + X0
+  beltBlockCopy(h, X);
+  beltBlockEncr2(h, buf);
+  beltBlockXor2(h, X);
+  // buf1 <- ~buf0 [buf12 == K2]
+  beltBlockNeg(buf + 4, buf);
+  // h1 <- beltBlock(X1, buf12) + X1
+  beltBlockCopy(h + 4, X + 4);
+  beltBlockEncr2(h + 4, buf + 4);
+  beltBlockXor2(h + 4, X + 4);
+}
+
+/**
+ * \brief Алгоритм сжатия belt-compress.
+ * \param s [4*32 бит] Указатель на выходное значение данных S.
+ * \param h [8*32 бит] Указатель на выходное значение Y <b>и второй половины входного значения X</b>.
+ * \param X [8*32 бит] Указатель на входное значение первой половины данных X.
+ * \param stack [12*32 бит] Указатель на промежуточный буфер работы функции.
+ */
+static inline void beltCompress2(ak_uint32 s[4], ak_uint32 h[8],
+                   const ak_uint32 X[8], void* stack) {
+  // [12]buf = [4]buf0 || [4]buf1 || [4]buf2
+  ak_uint32* buf = (ak_uint32*)stack;
+  // buf0, buf1 <- h0 + h1
+  beltBlockXor(buf, h, h + 4);
+  beltBlockCopy(buf + 4, buf);
+  // buf0 <- beltBlock(buf0, X) + buf1
+  beltBlockEncr2(buf, X);
+  beltBlockXor2(buf, buf + 4);
+  // s <- s ^ buf0
+  beltBlockXor2(s, buf);
+  // buf2 <- h0
+  beltBlockCopy(buf + 8, h);
+  // buf1 <- h1 [buf01 == K1]
+  beltBlockCopy(buf + 4, h + 4);
+  // h0 <- beltBlock(X0, buf01) + X0
+  beltBlockCopy(h, X);
+  beltBlockEncr2(h, buf);
+  beltBlockXor2(h, X);
+  // buf1 <- ~buf0 [buf12 == K2]
+  beltBlockNeg(buf + 4, buf);
+  // h1 <- beltBlock(X1, buf12) + X1
+  beltBlockCopy(h + 4, X + 4);
+  beltBlockEncr2(h + 4, buf + 4);
+  beltBlockXor2(h + 4, X + 4);
+}
+
+//---------------------------------------------------------
+//----------------------belt-hash--------------------------
+//---------------------------------------------------------
+
+#define beltBlockSetZero(block)\
+  ((ak_uint32*)(block))[0] = 0,\
+  ((ak_uint32*)(block))[1] = 0,\
+  ((ak_uint32*)(block))[2] = 0,\
+  ((ak_uint32*)(block))[3] = 0
+
+ak_uint32 u32Rev(ak_uint32 w) {
+  return w << 24 | (w & 0xFF00) << 8 | (w >> 8 & 0xFF00) | w >> 24;
+}
+
+#define beltBlockRevU32(block)\
+  ((ak_uint32*)(block))[0] = u32Rev(((ak_uint32*)(block))[0]),\
+  ((ak_uint32*)(block))[1] = u32Rev(((ak_uint32*)(block))[1]),\
+  ((ak_uint32*)(block))[2] = u32Rev(((ak_uint32*)(block))[2]),\
+  ((ak_uint32*)(block))[3] = u32Rev(((ak_uint32*)(block))[3])
+
+static int ak_hash_context_belt_hash_clean( ak_pointer bctx ) {
+  ak_belt_hash cx = ( ak_belt_hash ) bctx;
+  if( cx == NULL ) return ak_error_null_pointer;
+
+  beltBlockSetZero(cx->ls);
+  beltBlockSetZero(cx->ls + 4);
+  memmove(cx->h, beltH(), 32);
+
+  return ak_error_ok;
+}
+
+static int ak_hash_context_belt_hash_update(
+    ak_pointer bctx, const ak_pointer in, const size_t size ) {
+  ak_belt_hash cx = ( ak_belt_hash ) bctx;
+  const ak_uint8* dt = (const ak_uint8*) in;
+  ak_uint64 count;
+  ak_uint64 count_for_r;
+  ak_uint32* carry;
+
+  if( cx == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
+                                               "using null pointer to internal streebog context" );
+  if(( !size ) || ( in == NULL )) return ak_error_ok;
+  if( size & 0x1F ) return ak_error_message( ak_error_wrong_length, __func__,
+                                      "data length is not a multiple of the length of the block" );
+
+  // обновить длину
+  count = size;
+  count_for_r = count << 3;
+  carry = (ak_uint32*) &count_for_r;
+
+  cx->ls[0] = carry[0];
+  cx->ls[1] = carry[1];
+  count_for_r = count >> 61;
+  cx->ls[2] = carry[0];
+  cx->ls[3] = 0;
+  
+
+  while (count >= 32)
+  {
+    beltBlockCopy(cx->block, dt);
+    beltBlockCopy(cx->block + 16, dt + 16);
+#ifndef AK_LITTLE_ENDIAN
+    beltBlockRevU32(st->block);
+    beltBlockRevU32(st->block + 16);
+#endif
+    beltCompress2(cx->ls + 4, cx->h, (ak_uint32*)cx->block, cx->stack);
+    dt += 32;
+    count -= 32;
+  }
+
+  return ak_error_ok;
+}
+
+static int ak_hash_context_belt_hash_finalize( ak_pointer bctx,
+  const ak_pointer in, const size_t size, ak_pointer out,
+  const size_t out_size )
+{
+  ak_belt_hash cx = ( ak_belt_hash ) bctx;
+  struct belt_hash bx[1]; //здесь должна изменяться копия контекста, а не оригинал
+  ak_uint32 carry;
+
+  if( cx == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
+                                               "using null pointer to internal streebog context" );
+  if( out == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
+                                                   "using null pointer to externl result buffer" );
+  if( size >= 32 ) return ak_error_message( ak_error_wrong_length, __func__,
+                                                                       "input length is too huge" );
+  
+  memcpy( bx, cx, sizeof( struct belt_hash ));
+
+  if(size) {
+    // обновить длину
+    carry = (ak_uint32) size << 3;
+    carry = (bx->ls[0] += carry) < carry;
+    carry = (bx->ls[1] += carry) < carry;
+    carry = (bx->ls[2] += carry) < carry;
+    bx->ls[3] += carry;
+
+    //отработать последний блок
+    memset(bx->block, 0, 32);
+    if (in != NULL) {
+      memcpy(bx->block, in, size);
+    }
+#ifndef AK_LITTLE_ENDIAN
+    beltBlockRevU32(bx->block);
+    beltBlockRevU32(bx->block + 16);
+#endif
+    beltCompress2(bx->ls + 4, bx->h, (ak_uint32*)bx->block, bx->stack);
+  }
+  beltCompress(bx->h, bx->ls, bx->stack);
+
+  memcpy(out, bx->h, ak_min(32, out_size));
+
+  return ak_error_ok;
+}
+
+/**
+ * \brief Инициализация контекста функции бесключевого хеширования СТБ 34.101.31-2020 (belt-hash).
+ * \param hctx Контекст функции хеширования, который будет заполнен
+ * \return Функция возвращает код ошибки или \ref ak_error_ok (в случае успеха)
+ */
+int ak_hash_create_belt_hash( ak_hash hctx )
+{
+  int error = ak_error_ok;
+
+  if( hctx == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
+                                                            "using null pointer to hash context" );
+  if(( hctx->oid = ak_oid_find_by_name( "belt-hash" )) == NULL )
+    return ak_error_message( ak_error_wrong_oid, __func__,
+                                           "incorrect internal search of belt-hash identifier" );
+  if(( error = ak_mac_create( &hctx->mctx, 32, &hctx->data.bctx,
+                                             ak_hash_context_belt_hash_clean,
+                                             ak_hash_context_belt_hash_update,
+                                             ak_hash_context_belt_hash_finalize )) != ak_error_ok )
+    return ak_error_message( error, __func__, "incorrect initialization of internal mac context" );
+
+  return ak_hash_context_belt_hash_clean( &hctx->data.bctx );
+}
diff --git a/source/ak_hash.c b/source/ak_hash.c
index f6e6149..f2060cb 100644
--- a/source/ak_hash.c
+++ b/source/ak_hash.c
@@ -1512,7 +1512,7 @@
   if( hctx == NULL ) return ak_error_message( ak_error_null_pointer, __func__,
                                                        "destroying null pointer to hash context" );
   hctx->oid = NULL;
-  memset( &hctx->data.sctx, 0, sizeof( struct streebog ));
+  memset( &hctx->data.sctx, 0, sizeof (&hctx->data) );
   if( ak_mac_destroy( &hctx->mctx ) != ak_error_ok )
     ak_error_message( ak_error_get_value(), __func__,
                                                     "incorrect cleaning of internal mac context" );
diff --git a/source/ak_oid.c b/source/ak_oid.c
index 9411cd8..b0921f3 100644
--- a/source/ak_oid.c
+++ b/source/ak_oid.c
@@ -69,6 +69,8 @@
  static const char *asn1_streebog256_i[] = { "1.2.643.7.1.1.2.2", NULL };
  static const char *asn1_streebog512_n[] = { "streebog512", "md_gost12_512", NULL };
  static const char *asn1_streebog512_i[] = { "1.2.643.7.1.1.2.3", NULL };
+ static const char *asn1_belt_hash_n[] = { "belt-hash", NULL };
+ static const char *asn1_belt_hash_i[] = { "1.2.112.0.2.0.34.101.31.81", NULL };
  static const char *asn1_crc64_n[] =       { "crc64", NULL };
  static const char *asn1_crc64_i[] =       { "1.2.643.2.52.1.2.2", NULL };
 
@@ -556,6 +558,10 @@ static struct oid libakrypt_oids[] =
   {{ sizeof( struct hash ), ( ak_function_create_object *) ak_hash_create_streebog512,
                               ( ak_function_destroy_object *) ak_hash_destroy, NULL, NULL, NULL },
                               ak_object_undefined, (ak_function_run_object *) ak_hash_ptr, NULL }},
+ { hash_function, algorithm, asn1_belt_hash_i, asn1_belt_hash_n, NULL,
+  {{ sizeof( struct hash ), ( ak_function_create_object *) ak_hash_create_belt_hash,
+                              ( ak_function_destroy_object *) ak_hash_destroy, NULL, NULL, NULL },
+                              ak_object_undefined, (ak_function_run_object *) ak_hash_ptr, NULL }},
 
  { hash_function, algorithm, asn1_crc64_i, asn1_crc64_n, NULL,
   {{ sizeof( struct hash ), ( ak_function_create_object *) ak_hash_create_crc64,
diff --git a/source/libakrypt.h b/source/libakrypt.h
index 9bcbf75..7d7c80c 100644
--- a/source/libakrypt.h
+++ b/source/libakrypt.h
@@ -881,6 +881,20 @@ extern "C" {
   size_t hsize;
 } *ak_streebog;
 
+/* ----------------------------------------------------------------------------------------------- */
+/*! \brief Структура для хранения внутренних данных функции хеширования семейства belt-hash */
+/* ----------------------------------------------------------------------------------------------- */
+ typedef struct belt_hash {
+  /*! \brief Блок [4]len || [4]s */
+  ak_uint32 ls[8];
+  /*! \brief Временное значение хэш-суммы */
+  ak_uint32 h[8];
+  /*! \brief Блок данных для шифрования */
+  ak_uint8 block[32];
+  /*! \brief Стек для работы beltCompr [12*4 байт] */
+  ak_uint8 stack[12*4];
+} *ak_belt_hash;
+
 /* ----------------------------------------------------------------------------------------------- */
 /*! \brief Контекст бесключевой функции хеширования. */
 /*! \details Класс предоставляет интерфейс для реализации бесключевых функций хеширования, построенных
@@ -891,7 +905,7 @@ extern "C" {
 
   Перед началом работы контекст функции хэширования должен быть инициализирован
   вызовом одной из функций инициализации, например, функции ak_hash_create_streebog256()
-  или функции ak_hash_create_streebog512().
+  или функции ak_ak_oid_find_by_name_create_streebog512().
   После завершения вычислений контекст должен быть освобожден с помощью функции
   ak_hash_destroy().                                                                       */
 /* ----------------------------------------------------------------------------------------------- */
@@ -904,6 +918,8 @@ extern "C" {
    union {
      /*! \brief Структура алгоритмов семейства Стрибог. */
       struct streebog sctx;
+     /*! \brief Структура алгоритма belt-hash. */
+      struct belt_hash bctx;
      /*! \brief Вектор значений для алгоритмов семейства crc64 */
       ak_uint64 b64;
    } data;
@@ -914,6 +930,8 @@ extern "C" {
  dll_export int ak_hash_create_streebog256( ak_hash );
 /*! \brief Инициализация контекста функции бесключевого хеширования ГОСТ Р 34.11-2012 (Стрибог512). */
  dll_export int ak_hash_create_streebog512( ak_hash );
+/*! \brief Инициализация контекста функции бесключевого хеширования СТБ 34.101.31-2020 (belt-hash). */
+ dll_export int ak_hash_create_belt_hash( ak_hash );
 /*! \brief Инициализация контекста некриптографической функции хеширования crc64. */
  dll_export int ak_hash_create_crc64( ak_hash );
 /*! \brief Инициализация контекста функции бесключевого хеширования по заданному OID алгоритма. */
-- 
GitLab


From 4b93c5e223ad4be0f2276f2a0dafcda6f842d630 Mon Sep 17 00:00:00 2001
From: Timothy Tur <tvtur@edu.hse.ru>
Date: Fri, 7 Feb 2025 15:15:04 +0300
Subject: [PATCH 41/41] restoring some for orig repo

---
 libakrypt.test.sh  | 2 +-
 source/libakrypt.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/libakrypt.test.sh b/libakrypt.test.sh
index 1bdf519..e648a8c 100755
--- a/libakrypt.test.sh
+++ b/libakrypt.test.sh
@@ -15,7 +15,7 @@ do
                 mkdir -p $name.build
                 cd $name.build
 # выполняем настройку
-                cmake -DCMAKE_C_COMPILER=$name -DAK_STATIC_LIB=ON -DAK_EXAMPLES=ON -DAK_TESTS=ON ../../libakrypt-0-x-belt-hash
+                cmake -DCMAKE_C_COMPILER=$name -DAK_STATIC_LIB=ON -DAK_EXAMPLES=ON -DAK_TESTS=ON ../../libakrypt-0.x
 # выполняем сборку
                 make
 # выполняем тестирование
diff --git a/source/libakrypt.h b/source/libakrypt.h
index 7d7c80c..89796d6 100644
--- a/source/libakrypt.h
+++ b/source/libakrypt.h
@@ -905,7 +905,7 @@ extern "C" {
 
   Перед началом работы контекст функции хэширования должен быть инициализирован
   вызовом одной из функций инициализации, например, функции ak_hash_create_streebog256()
-  или функции ak_ak_oid_find_by_name_create_streebog512().
+  или функции ak_hash_create_streebog512().
   После завершения вычислений контекст должен быть освобожден с помощью функции
   ak_hash_destroy().                                                                       */
 /* ----------------------------------------------------------------------------------------------- */
-- 
GitLab