Created
December 9, 2021 22:53
-
-
Save tmtvl/014413829fab3a46998f71ca9e047f81 to your computer and use it in GitHub Desktop.
Implementation of MD5 algo based on https://en.wikipedia.org/wiki/MD5
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Based on <https://en.wikipedia.org/wiki/MD5> | |
/************/ | |
/* INCLUDES */ | |
/************/ | |
#include <limits.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
/*************/ | |
/* CONSTANTS */ | |
/*************/ | |
const unsigned int SHIFT_ROUNDS[64] = | |
{ | |
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 | |
}; | |
const unsigned int CONSTANTS[64] = | |
{ | |
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 | |
}; | |
const unsigned int INITIAL_A = 0x67452301; | |
const unsigned int INITIAL_B = 0xefcdab89; | |
const unsigned int INITIAL_C = 0x98badcfe; | |
const unsigned int INITIAL_D = 0x10325476; | |
/**************/ | |
/* PROCEDURES */ | |
/**************/ | |
int | |
leftrotate (unsigned int x, unsigned int y) | |
{ | |
unsigned int steps = y % 32; | |
return (x << steps) | (x >> (32 - steps)); | |
} | |
void | |
md5_process_words (unsigned int words[], | |
unsigned int *a, unsigned int *b, | |
unsigned int *c, unsigned int *d) | |
{ | |
unsigned int f, g, i, xa, xb, xc, xd; | |
xa = *a; | |
xb = *b; | |
xc = *c; | |
xd = *d; | |
for (i = 0; i < 64; i++) | |
{ | |
if (i < 16) | |
{ | |
f = (xb & xc) | ((~xb) & xd); | |
g = i; | |
} | |
else if (i < 32) | |
{ | |
f = (xd & xb) | ((~xd) & xc); | |
g = ((i * 5) + 1) % 16; | |
} | |
else if (i < 48) | |
{ | |
f = xb ^ xc ^ xd; | |
g = ((i * 3) + 5) % 16; | |
} | |
else | |
{ | |
f = xc ^ (xb | (~xd)); | |
g = (i * 7) % 16; | |
} | |
f += xa + CONSTANTS[i] + words[g]; | |
xa = xd; | |
xd = xc; | |
xc = xb; | |
xb += leftrotate (f, SHIFT_ROUNDS[i]); | |
} | |
*a += xa; | |
*b += xb; | |
*c += xc; | |
*d += xd; | |
} | |
void | |
md5_process_chunk (char *chunk, | |
unsigned int *a, unsigned int *b, | |
unsigned int *c, unsigned int *d) | |
{ | |
unsigned int *words = NULL; | |
words = (unsigned int *) chunk; | |
md5_process_words (words, a, b, c, d); | |
} | |
void | |
md5_print (int part) | |
{ | |
unsigned char bytes[4] = { | |
(char) (part & 0xFF), | |
(char) ((part >> 0x8) & 0xFF), | |
(char) ((part >> 0x10) & 0xFF), | |
(char) ((part >> 0x18) & 0xFF) | |
}; | |
printf ("%02x%02x%02x%02x", bytes[0], bytes[1], bytes[2], bytes[3]); | |
} | |
void | |
md5 (const char *bytes, const int len) | |
{ | |
char *msg; | |
int i, msg_len; | |
unsigned int a, b, c, d; | |
/* | |
* If the length of the input (mod 64) is less than 56 we pad it out to 56. | |
* Otherwise we pad it out to 120 so we can get the additional 1 bit in. | |
*/ | |
msg_len = 56 - (len % 64); | |
if (msg_len < 1) | |
msg_len += 64; | |
// Add space for the original length in bits. | |
msg_len += len + 8; | |
// calloc zeroes out the memory, so we don't have to worry about 0-padding. | |
msg = calloc (msg_len, sizeof (char)); | |
memcpy (msg, bytes, len); | |
// Add the '1' bit after the original message. | |
// 0x80 = 0b1000_0000; | |
msg[len] = (char) 0x80; | |
// Set a to the length in bits, which is 8 * length in bytes. | |
a = len << 3; | |
// Add the length in bits to the end of the message. | |
memcpy (&msg[msg_len - 8], &a, 4); | |
a = INITIAL_A; | |
b = INITIAL_B; | |
c = INITIAL_C; | |
d = INITIAL_D; | |
for (i = 0; i < msg_len; i += 64) | |
md5_process_chunk (&msg[i], &a, &b, &c, &d); | |
md5_print (a); | |
md5_print (b); | |
md5_print (c); | |
md5_print (d); | |
puts (""); | |
free (msg); | |
} | |
int | |
main (int argc, char *argv[]) | |
{ | |
int i; | |
for (i = 1; i < argc; i++) | |
md5 (argv[i], strlen (argv[i])); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment