Skip to content

Instantly share code, notes, and snippets.

@tmtvl
Created December 9, 2021 22:53
Show Gist options
  • Save tmtvl/014413829fab3a46998f71ca9e047f81 to your computer and use it in GitHub Desktop.
Save tmtvl/014413829fab3a46998f71ca9e047f81 to your computer and use it in GitHub Desktop.
Implementation of MD5 algo based on https://en.wikipedia.org/wiki/MD5
// 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