init
This commit is contained in:
commit
843cbdcdf1
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.vscode/settings.json
|
||||||
|
obj*
|
||||||
|
bin*
|
23
Makefile
Normal file
23
Makefile
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
CC = clang
|
||||||
|
CFLAGS = -Wall -Wextra -pedantic -std=c17 -g
|
||||||
|
SRCS = src/main.c src/md5.c
|
||||||
|
OBJS = $(SRCS:src/%.c=obj/%.o)
|
||||||
|
|
||||||
|
TARGET = bin/md5hash
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
$(TARGET): $(OBJS)
|
||||||
|
mkdir -p bin
|
||||||
|
$(CC) $(OBJS) -o $@
|
||||||
|
|
||||||
|
obj/%.o: src/%.c | obj
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
obj:
|
||||||
|
mkdir -p obj
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf ./obj $(TARGET)
|
||||||
|
|
||||||
|
.PHONY: clean
|
3
README.md
Normal file
3
README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# MD5 Hash Calculator
|
||||||
|
|
||||||
|
Simple MD5 realization for small amounts of data written on pure C for Linux
|
56
src/main.c
Normal file
56
src/main.c
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "md5.h"
|
||||||
|
|
||||||
|
void returnHash(uint8_t* digest);
|
||||||
|
|
||||||
|
int main(int argc, char** argv){
|
||||||
|
if(argc > 1)
|
||||||
|
{
|
||||||
|
char* argData = argv[1];
|
||||||
|
FILE* sFile = fopen(argData, "rb");
|
||||||
|
uint8_t output[16]; //128-bit buffer
|
||||||
|
|
||||||
|
if(sFile == NULL){
|
||||||
|
md5((uint8_t*) argData, strlen(argData), output);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
//Prepare data for stream into md5
|
||||||
|
fseek(sFile, 0, SEEK_END);
|
||||||
|
unsigned long fileSize = ftell(sFile);
|
||||||
|
rewind(sFile);
|
||||||
|
uint8_t *stream = (uint8_t*)malloc(fileSize);
|
||||||
|
if (!stream) {
|
||||||
|
fclose(sFile);
|
||||||
|
errno = -1;
|
||||||
|
perror("malloc() failed. Maybe file is too big?");
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
size_t readSize = fread(stream, 1, fileSize, sFile);
|
||||||
|
|
||||||
|
fclose(sFile);
|
||||||
|
if (readSize != fileSize) {
|
||||||
|
free(stream);
|
||||||
|
errno = -2;
|
||||||
|
perror("Failed to read file. Maybe file is too big?");
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
md5(stream, fileSize, output);
|
||||||
|
}
|
||||||
|
returnHash(output);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
errno = 1;
|
||||||
|
perror("There is no input for generate MD5 hash");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void returnHash(uint8_t* digest){
|
||||||
|
for (size_t i = 0; i < 16; i++) {
|
||||||
|
printf("%02x", digest[i]);
|
||||||
|
}
|
||||||
|
}
|
118
src/md5.c
Normal file
118
src/md5.c
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// Левое циклическое вращение (ROTATE LEFT)
|
||||||
|
#define LEFT_ROTATE(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||||
|
|
||||||
|
// Константы для сдвигов
|
||||||
|
static const uint8_t s[] = {
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
// Таблица предварительно вычисленных констант
|
||||||
|
static const 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
|
||||||
|
};
|
||||||
|
|
||||||
|
// Функции для раундов
|
||||||
|
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
|
||||||
|
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
|
||||||
|
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||||
|
#define I(x, y, z) ((y) ^ ((x) | (~z)))
|
||||||
|
|
||||||
|
void md5(const uint8_t *initial_msg, size_t initial_len, uint8_t *digest) {
|
||||||
|
// Инициализация буфера
|
||||||
|
uint32_t a0 = 0x67452301;
|
||||||
|
uint32_t b0 = 0xefcdab89;
|
||||||
|
uint32_t c0 = 0x98badcfe;
|
||||||
|
uint32_t d0 = 0x10325476;
|
||||||
|
|
||||||
|
// Вычисление необходимой длины сообщения с дополнением
|
||||||
|
size_t new_len = (((initial_len + 8) / 64) + 1) * 64;
|
||||||
|
uint8_t *msg = (uint8_t*)malloc(new_len);
|
||||||
|
memcpy(msg, initial_msg, initial_len);
|
||||||
|
msg[initial_len] = 0x80; // Добавление бита "1"
|
||||||
|
|
||||||
|
// Заполнение нулями
|
||||||
|
for (size_t i = initial_len + 1; i < new_len - 8; i++) {
|
||||||
|
msg[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Добавление длины сообщения в битах (little-endian)
|
||||||
|
uint64_t bit_len = (uint64_t)initial_len * 8;
|
||||||
|
memcpy(msg + new_len - 8, &bit_len, 8);
|
||||||
|
|
||||||
|
// Обработка сообщения блоками по 64 байта
|
||||||
|
for (size_t offset = 0; offset < new_len; offset += 64) {
|
||||||
|
// Разбиение текущего блока на 16 слов
|
||||||
|
uint32_t M[16];
|
||||||
|
for (size_t i = 0; i < 16; i++) {
|
||||||
|
M[i] = *(uint32_t*)(msg + offset + i * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Инициализация рабочих переменных
|
||||||
|
uint32_t A = a0;
|
||||||
|
uint32_t B = b0;
|
||||||
|
uint32_t C = c0;
|
||||||
|
uint32_t D = d0;
|
||||||
|
|
||||||
|
// Основной цикл (64 шага)
|
||||||
|
for (size_t i = 0; i < 64; i++) {
|
||||||
|
uint32_t F, g;
|
||||||
|
if (i < 16) {
|
||||||
|
F = F(B, C, D);
|
||||||
|
g = i;
|
||||||
|
} else if (i < 32) {
|
||||||
|
F = G(B, C, D);
|
||||||
|
g = (5 * i + 1) % 16;
|
||||||
|
} else if (i < 48) {
|
||||||
|
F = H(B, C, D);
|
||||||
|
g = (3 * i + 5) % 16;
|
||||||
|
} else {
|
||||||
|
F = I(B, C, D);
|
||||||
|
g = (7 * i) % 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Вычисление нового значения
|
||||||
|
F = F + A + K[i] + M[g];
|
||||||
|
A = D;
|
||||||
|
D = C;
|
||||||
|
C = B;
|
||||||
|
B = B + LEFT_ROTATE(F, s[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обновление состояния
|
||||||
|
a0 += A;
|
||||||
|
b0 += B;
|
||||||
|
c0 += C;
|
||||||
|
d0 += D;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(msg);
|
||||||
|
|
||||||
|
// Формирование итогового дайджеста в порядке little-endian
|
||||||
|
memcpy(digest, &a0, 4);
|
||||||
|
memcpy(digest + 4, &b0, 4);
|
||||||
|
memcpy(digest + 8, &c0, 4);
|
||||||
|
memcpy(digest + 12, &d0, 4);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user