Finished writing this a little while ago but unfortunately the generated MD5 doesn't match other application's hashes.
I have basically used Wikipedia for reference. I have a feeling my error is introduced in the padding stage but I can't be certain, hoping a fresh set of eyes could point out the issue for me so I can get on and fix it!
int k[64];
int 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};
int left_rotate(int x, int c)
{
return (x << c) | (x >> (32 - c));
}
void c_md5::md5(const char *input, int length)
{
int h0 = 0x67452301;
int h1 = 0xEFCDAB89;
int h2 = 0x98BADCFE;
int h3 = 0x10325476;
char *buffer;
int bufLen;
// set k
for(int loop = 0; loop < 64; loop++)
{
floor(fabs(sin(loop + 1)) * (pow(2, 32)));
}
// get the original input length
bufLen = length;
if((bufLen % 64) > 0)
{
if(64 - bufLen < 8)
{
bufLen += 64;
}
int tempVal;
tempVal = bufLen % 64;
bufLen += 64 - tempVal;
}
printf("Checking if buffer length is divisible by 64... ");
if(bufLen % 64 == 0)
{
printf("done!\n");
}
else
{
printf("failed!\n");
return;
}
// create our new buffer
buffer = new char [bufLen];
printf("Checking if buffer is created... ");
if(buffer)
{
printf("done!\n");
}
else
{
printf("failed\n");
return;
}
// copy content over
for(int loop = 0; loop < length; loop++)
{
buffer[loop] = input[loop];
}
// blank remaining bits
for(int loop = length; loop < bufLen; loop++)
{
buffer[loop] = 0x0;
}
// fill in the length of the original stream into the padding
{
int tempLength = length * 8;
int tempVal;
tempVal = tempLength;
// use some bitwise shifting to access the length correctly
buffer[bufLen - 1] = (char)tempVal;
tempVal = tempLength >> 8;
buffer[bufLen - 2] = (char)tempVal;
tempVal = tempLength >> 16;
buffer[bufLen - 3] = (char)tempVal;
tempVal = tempLength >> 24;
buffer[bufLen - 4] = (char)tempVal;
}
printf("Checking reported length = stream length... ");
if((unsigned char)buffer[bufLen - 4] * 256 * 256 * 256 + (unsigned char)buffer[bufLen - 3] * 256 * 256 + (unsigned char)buffer[bufLen - 2] * 256 + (unsigned char)buffer[bufLen - 1] == length * 8)
{
printf("done!\n");
}
else
{
printf("failed!\n");
printf("length (in bits) : %i\n", length * 8);
printf("padding(in bits) : %i\n", (unsigned char)buffer[bufLen - 4] * 256 * 256 * 256 + (unsigned char)buffer[bufLen - 3] * 256 * 256 + (unsigned char)buffer[bufLen - 2] * 256 + (unsigned char)buffer[bufLen - 1]);
return;
}
// set the first bit of the padding
buffer[length] = buffer[length] | 0x80;
// below based on psuedo code from Wikipedia
for(int MD5_loop = 0; MD5_loop < bufLen / 64; MD5_loop++)
{
int a, b, c, d;
a = h0;
b = h1;
c = h2;
d = h3;
int word[16];
for(int loop = 0; loop < 16; loop++)
{
word[loop] = buffer[MD5_loop * 64 + loop * 16];
}
int f, g, tempVal;
for(int loop = 0; loop < 64; loop++)
{
if(loop < 16)
{
f = ((b & c) | (!b) & d);
g = loop;
}
else if(loop < 32)
{
f = ((d & b) | (!d) & c);
g = (5 * loop + 1) % 16;
}
else if(loop < 48)
{
f = (b ^ c ^ d);
g = (3 * loop + 5) % 16;
}
else if(loop < 64)
{
f = (c ^ (b | (!d)));
g = (7 * loop) % 16;
}
tempVal = d;
d = c;
c = b;
b = b + left_rotate(a + f + k[loop] + word[g], r[loop]);
a = tempVal;
}
h0 += a;
h1 += b;
h2 += c;
h3 += d;
}
printf("%04X%04X%04X%04X\n", h0, h1, h2, h3);
}
Cheers!