Реализация алгоритма без использования динамического выделения памяти

This commit is contained in:
re.kovalev 2022-03-16 11:41:30 +03:00
parent a6dc6f13de
commit 2413f63569
1 changed files with 185 additions and 0 deletions

185
main.c Normal file
View File

@ -0,0 +1,185 @@
#include <stdio.h>
#include <stdlib.h>
// memcpy
#include <string.h>
// uint8_t, uint32_t
#include <stdint.h>
// размер чанка
#define CHUNK_SIZE 64
// функции раундов
#define funcF(x, y, z) ((x & y) | ((~x) & z))
#define funcG(x, y, z) ((x & z) | ((~z) & y))
#define funcH(x, y, z) (x ^ y ^ z)
#define funcI(x, y, z) (y ^ ((~z) | x))
// битовый сдвиг
#define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
void md5(uint8_t *data, size_t size, uint32_t *result)
{
// размеры сдвигов
uint32_t r[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21};
// таблица констант
uint32_t k[] = {
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391};
// инициализация переменных под результат
result[0] = 0x67452301;
result[1] = 0xefcdab89;
result[2] = 0x98badcfe;
result[3] = 0x10325476;
size_t bits_len = size * 8; // длина хешируемых данных в битах
int chunk_i; // счетчик цикла по чанкам
uint8_t chunk[CHUNK_SIZE]; // чанк (64 байта = 512 бит)
uint8_t sub_chunk[2][CHUNK_SIZE]; // доп. чанк для остатка данных (56 байт = 448 бит + 2 байта bits_len)
int sub_chunk_flag = 0; // флаг наличия доп. чанка, а так же помогает взять нужный чанк на копирование
int chunk_count = size / CHUNK_SIZE; // количество чанков
uint32_t *chunk_4b; // 32 битное представление элемента чанка для мат операций (64 байта в 16 элементах)
uint32_t a, b, c, d; // переменные для расчетов в раундах
uint32_t i; // счетчик цикла для раундов
uint32_t temp; // буфер для перестановки местами значений двух переменных
uint32_t f, g; // результат функции раунда и индекс в массиве чанка
// цикл по чанкам
for (chunk_i = 0; chunk_i <= chunk_count; chunk_i++)
{
// обнуляем чанк
memset(chunk, 0, CHUNK_SIZE);
// если индекс меньше кол-ва чанков - используется полный размер чанка
if (chunk_i < chunk_count)
{
// копируем данные в чанк
memcpy(chunk, data + (chunk_i * CHUNK_SIZE), CHUNK_SIZE);
} // if (chunk_i < chunk_count) then если индекс меньше кол-ва чанков
// иначе требуется сформировать по правилам (добавить бит и в конце дописать размер данных в битах)
else
{
// если флаг не установлен, производится подготовка доп чанка
if (sub_chunk_flag == 0)
{
// установка флага для единичной инициализации
sub_chunk_flag = 1;
// обнулим чанки
memset(sub_chunk, 0, CHUNK_SIZE * 2);
// скопируем данные в первый чанк
memcpy(sub_chunk, data + (chunk_i * CHUNK_SIZE), (size % CHUNK_SIZE));
// допишем в конец данных единичный бит
sub_chunk[0][size % CHUNK_SIZE] = 128;
// если остаток от деления размера данных на размер чанка позволяет записать байт с единичным битом и размер данных (в битах) 8 байт (16 бит)
if ((size % CHUNK_SIZE) <= 55)
{
// то используется только один доп чанк, скопируем размер данных (в битах)
memcpy(&sub_chunk[0][56], &bits_len, sizeof(bits_len));
} // if ((size % CHUNK_SIZE) <= 55) then
else
{
// иначе используется второй доп чанк
memcpy(&sub_chunk[1][56], &bits_len, sizeof(bits_len));
// отнимем единицу у счетчика - еще один заход на доп. чанк
chunk_i--;
} // if ((size % CHUNK_SIZE) <= 55) else
} // if (sub_chunk_flag == 0) если флаг не установлен, производится подготовка доп чанка
// копируется доп чанк в соответсвии с значением флага-1
memcpy(chunk, sub_chunk[sub_chunk_flag - 1], CHUNK_SIZE);
sub_chunk_flag++; // инкремент на случай следующей итерации со вторым доп чанком
} // if (chunk_i < chunk_count) else если индекс больше или равен кол-ву чанков
// 4 байтовый указатель на чанк (16 эл-тов)
chunk_4b = (uint32_t *)chunk;
// инициализируем переменные для расчетов
a = result[0];
b = result[1];
c = result[2];
d = result[3];
// цикл основных преобразований
for (i = 0; i < 64; i++)
{
// определяем раунд
switch (i / 16)
{
case 0:
f = funcF(b, c, d);
g = i;
break;
case 1:
f = funcG(b, c, d);
g = (5 * i + 1) % 16;
break;
case 2:
f = funcH(b, c, d);
g = (3 * i + 5) % 16;
break;
case 3:
f = funcI(b, c, d);
g = (7 * i) % 16;
break;
} // switch(i/16) определяем раунд
// преобразования
temp = d;
d = c;
c = b;
b += LEFTROTATE((a + f + k[i] + chunk_4b[g]), r[i]);
a = temp;
} // for(i) цикл основных преобразований
// после прохода чанка - модифицируем переменную результата
result[0] += a;
result[1] += b;
result[2] += c;
result[3] += d;
} // for(chunk_i) цикл по чанкам
} // void md5(uint8_t *data, size_t size, uint32_t *result)
int main(int argc, char *argv[])
{
char msg[] = "md5";
size_t len = sizeof(msg) - 1; // минус нуль-терминатор
// результат
uint32_t result[4];
// вызов хеш-функции
md5((uint8_t *)msg, len, result);
//вывод результата в формате little-endian
uint8_t *p;
p = (uint8_t *)&result[0];
printf("%2.2x%2.2x%2.2x%2.2x ", p[0], p[1], p[2], p[3]);
p = (uint8_t *)&result[1];
printf("%2.2x%2.2x%2.2x%2.2x ", p[0], p[1], p[2], p[3]);
p = (uint8_t *)&result[2];
printf("%2.2x%2.2x%2.2x%2.2x ", p[0], p[1], p[2], p[3]);
p = (uint8_t *)&result[3];
printf("%2.2x%2.2x%2.2x%2.2x\n", p[0], p[1], p[2], p[3]);
//"1111111111111111111111111111111111111111111111111111111111111111" = 46f04863 257ac804 0905ea00 02183d35
//"1" = c4ca4238 a0b92382 0dcc509a 6f75849b
//"md5" = 1bc29b36 f623ba82 aaf6724f d3b16718
return 0;
}