Реализация алгоритма без использования динамического выделения памяти
This commit is contained in:
parent
a6dc6f13de
commit
2413f63569
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue