diff --git a/software/gost28147/CMakeLists.txt b/software/gost28147/CMakeLists.txt new file mode 100644 index 0000000..eefe04c --- /dev/null +++ b/software/gost28147/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.8) # Проверка версии CMake. + # Если версия установленой программы + # старее указаной, произойдёт аварийный выход. +project(Gost28147) + +add_definitions(-D_CRT_SECURE_NO_WARNINGS) + +include_directories(.) + +list(APPEND sources + ./Gost28147.cpp + ./main.cpp) + +add_executable(Gost28147 ${sources}) # Создает исполняемый файл с именем + # из исходника .cpp \ No newline at end of file diff --git a/software/gost28147/Gost28147.cpp b/software/gost28147/Gost28147.cpp new file mode 100644 index 0000000..bcdba08 --- /dev/null +++ b/software/gost28147/Gost28147.cpp @@ -0,0 +1,136 @@ +#include "Gost28147.h" + +void Gost28147_encode(uint8_t* blockin, uint8_t* blockout, uint32_t* Key, uint8_t** SubTable) +{ + uint8_t first_uint8_t, second_uint8_t, zam_symbol, n; + int8_t q; + + uint32_t n1 = 0, n2 = 0, SUM232 = 0; // накопители N1, N2, и сумматор + + n1 = *((uint32_t *)&blockin[0]); + n2 = *((uint32_t *)&blockin[4]); + + // 32 цикла простой замены + // ключ считываем в требуемом ГОСТом порядке + int8_t c = 0; + for (uint8_t k = 0; k<32; k++) + { + if (k == 24) + c = 7; + + // суммируем в сумматоре СМ1 + SUM232 = Key[c] + n1; + + // заменяем по таблице замен + first_uint8_t = 0, second_uint8_t = 0, zam_symbol = 0; + n = 7; + for (q = 3; q >= 0; q--) + { + zam_symbol = *((uint8_t *)&SUM232 + q); + first_uint8_t = (zam_symbol & 0xF0) >> 4; + second_uint8_t = (zam_symbol & 0x0F); + first_uint8_t = SubTable[n][first_uint8_t]; + n--; + second_uint8_t = SubTable[n][second_uint8_t]; + n--; + zam_symbol = (first_uint8_t << 4) | second_uint8_t; + *((uint8_t *)&SUM232 + q) = zam_symbol; + } + + SUM232 = (SUM232 << 11) | (SUM232 >> 21); // циклический сдвиг на 11 + SUM232 = n2^SUM232; // складываем в сумматоре СМ2 + + if (k<31) + { + n2 = n1; + n1 = SUM232; + } + + if (k<24) + { + c++; + if (c>7) c = 0; + } + else + { + c--; + if (c<0) c = 7; + } + } + n2 = SUM232; + + // записываем результат + uint8_t ind = 0; + for (q = 0; q <= 3; q++) + blockout[ind++] = *((uint8_t *)&n1 + q); + + for (q = 0; q <= 3; q++) + blockout[ind++] = *((uint8_t *)&n2 + q); +} + +void Gost28147_decode(uint8_t* blockin, uint8_t* blockout, uint32_t* Key, uint8_t** SubTable) +{ + uint8_t first_uint8_t, second_uint8_t, zam_symbol, n; + int8_t q; + + uint32_t n1 = 0, n2 = 0, SUM232 = 0; // накопители N1, N2, и сумматор + + n1 = *((uint32_t *)&blockin[0]); + n2 = *((uint32_t *)&blockin[4]); + + // 32 цикла простой замены + // ключ считываем в требуемом ГОСТом порядке + int8_t c = 0; + for (uint8_t k = 0; k<32; k++) + { + if (k == 8) c = 7; + + // суммируем в сумматоре СМ1 + SUM232 = Key[c] + n1; + + // заменяем по таблице замен + first_uint8_t = 0, second_uint8_t = 0, zam_symbol = 0; + n = 7; + for (q = 3; q >= 0; q--) + { + zam_symbol = *((uint8_t *)&SUM232 + q); + first_uint8_t = (zam_symbol & 0xF0) >> 4; + second_uint8_t = (zam_symbol & 0x0F); + first_uint8_t = SubTable[n][first_uint8_t]; + n--; + second_uint8_t = SubTable[n][second_uint8_t]; + n--; + zam_symbol = (first_uint8_t << 4) | second_uint8_t; + *((uint8_t *)&SUM232 + q) = zam_symbol; + } + + SUM232 = (SUM232 << 11) | (SUM232 >> 21); // циклический сдвиг на 11 + SUM232 = n2^SUM232; // складываем в сумматоре СМ2 + + if (k<31) + { + n2 = n1; + n1 = SUM232; + } + + if (k<8) + { + c++; + if (c>7) c = 0; + } + else + { + c--; + if (c<0) c = 7; + } + } + n2 = SUM232; + + // записываем результат + uint8_t ind = 0; + for (q = 0; q <= 3; q++) + blockout[ind++] = *((uint8_t *)&n1 + q); + + for (q = 0; q <= 3; q++) + blockout[ind++] = *((uint8_t *)&n2 + q); +} \ No newline at end of file diff --git a/software/gost28147/Gost28147.h b/software/gost28147/Gost28147.h new file mode 100644 index 0000000..b26d979 --- /dev/null +++ b/software/gost28147/Gost28147.h @@ -0,0 +1,27 @@ +#ifndef GOST28147LIB +#define GOST28147LIB + +#include + +/** +* \brief Набор функций, реализующих алгоритм шифрования по ГОСТ 28147-89. +* \version 1.0. +* \date 29 марта 2017 года. +* +* Алгоритм криптографического преобразования описан в стандарте ГОСТ 28147-89. +* Доступный режим зашифрования (расшифрования) данных - режим простой замены. +* Ключ длиной 256 бит разбивается на 8 32-битных блоков. +* Блок подстановки (таблица замен) состоит из 8-и узлов замены, каждый из которых имеет длину 64 бита. +* Поступающий на блок подстановки 32-разрядный вектор разбивается на 8 последовательно идущих 4-разрядных +* векторов, каждый из которых преобразуется в 4-разрядный вектор соответствующим узлом замены, представляющим +* собой таблицу из шестнадцати строк, содержащих по четыре бита заполнения в строке. Входной вектор определяет +* адрес строки в таблице, заполнение данной строки является выходным вектором. Затем 4-разрядные выходные +* векторы последовательно объединяются в 32-разрядный вектор. +*/ + +///< Функция Gost28147_encode выполняет зашифрования по ГОСТ 28147-89. +void Gost28147_encode(uint8_t* blockin, uint8_t* blockout, uint32_t* Key, uint8_t** SubTable); +///< Функция Gost28147_encode выполняет расшифрования по ГОСТ 28147-89. +void Gost28147_decode(uint8_t* blockin, uint8_t* blockout, uint32_t* Key, uint8_t** SubTable); + +#endif \ No newline at end of file diff --git a/software/gost28147/main.cpp b/software/gost28147/main.cpp new file mode 100644 index 0000000..1f2e3e6 --- /dev/null +++ b/software/gost28147/main.cpp @@ -0,0 +1,131 @@ +#include +#include +#include "Gost28147.h" + +long filesize(FILE *stream); + +using namespace std; + +int main(int argc, char** argv) +{ + if (argc != 4) + { + printf("Usage:\n\tgost-28147-89.exe \n\tmode = 1 - encoding\n\tmode = 2 - decoding\nInput any key to continue..."); + getchar(); + return EXIT_FAILURE; + } + + uint32_t* Key = (uint32_t*)malloc(8 * sizeof(uint32_t)); + Key[0] = 0x0123; + Key[1] = 0x4567; + Key[2] = 0x89AB; + Key[3] = 0xCDEF; + Key[4] = 0x0123; + Key[5] = 0x4567; + Key[6] = 0x89AB; + Key[7] = 0xCDEF; + + uint8_t** SubTable; + SubTable = (uint8_t**)malloc(8 * sizeof(uint8_t*)); + for (int i = 0; i < 8; i++) + { + SubTable[i] = (uint8_t*)malloc(16 * sizeof(uint8_t)); + for (int j = 0; j < 16; j++) + SubTable[i][j] = j; + } + + // режим, 1 - зашифрование, 2 - расшифрование + int mode; + sscanf(argv[1], "%d", &mode); + + FILE *f_in, *f_out; // потоки для входного и выходного файлов + + // открываем файлы + f_in = fopen(argv[2], "rb"); + f_out = fopen(argv[3], "wb"); + + // считываем входные данные + long inputsize = filesize(f_in); + + // Определяем размер входные данных + float blokoff; + blokoff = (float)8 * inputsize; + blokoff = blokoff / 64; + int blockN = (int)blokoff; + if (blokoff - blockN>0) blockN++; + + int sh; + if (inputsize >= 4) sh = 4; else sh = inputsize; + int sh1 = 0; + int flag = 0; + + uint8_t blockin[9]; + uint8_t blockout[9]; + blockin[8] = '\0'; + blockout[8] = '\0'; + + for (int i = 0; i < blockN; i++) + { + for (int q = 0; q < 8; q++) + { + *((uint8_t *)&blockin + q) = 0x00; + *((uint8_t *)&blockout + q) = 0x00; + } + + if ((sh1 + sh) < inputsize) + { + fread(&blockin[0], sh, 1, f_in); + sh1 += sh; + } + else + { + sh = inputsize - sh1; + fread(&blockin[0], sh, 1, f_in); + flag = 1; + } + + if ((sh1 + sh) < inputsize) + { + fread(&blockin[4], sh, 1, f_in); + sh1 += sh; + } + else + { + if (flag == 0) + { + sh = inputsize - sh1; + fread(&blockin[4], sh, 1, f_in); + } + } + + if (mode == 1) + Gost28147_encode(blockin, blockout, Key, SubTable); + else if (mode == 2) + Gost28147_decode(blockin, blockout, Key, SubTable); + else + { + printf("Wrong mode. Exit. Press any key to continue..."); + getchar(); + return EXIT_FAILURE; + } + + // Выводим результат в файл + fwrite(&blockout[0], 8, 1, f_out); + } + + // закрываем файлы + fclose(f_in); + fclose(f_out); + + return EXIT_SUCCESS; +} + +long filesize(FILE * stream) +{ + long curpos, length; + curpos = ftell(stream); + fseek(stream, 0L, SEEK_END); + length = ftell(stream); + fseek(stream, curpos, SEEK_SET); + return length; +} \ No newline at end of file