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