# C and C++ MD5 algorithm implementation code

• 2020-05-26 09:52:16
• OfStack

In the reverse program, we often encounter the problem of encryption algorithm. In the previous analysis of question 2 of the reverse engineer of UC, we found that the encryption algorithm of MD5 was used (the algorithm of MD5 is realized by ourselves, not the algorithm library function). Especially in the reverse analysis of network protocol, 1 - like programs used encryption algorithm is the library function provided by the algorithm, some programs use the algorithm is their own implementation; Relatively speaking, the encryption function algorithm provided by the function library is relatively easy to identify, because there are common functions in the algorithm; However, if you do not use the function library to provide encryption function but to implement some algorithms, it is difficult to identify, which requires you to be familiar with the function encryption principle and process algorithm features to quickly identify. The following will be online about MD5 algorithm 1 some knowledge 1, aspects of their own reference.

md5 profile

md5 algorithm description

Assuming that the length of the input message (input message) is b(bit), we want to generate its message digest, where b is an arbitrary non-negative integer: b may also be 0, nor is 1 an integer multiple of 8, and may be of an arbitrarily large length. Let the bitstream of this information be represented as follows: M M M... To calculate the message digest for this information, M[b-1] requires the following five steps:

1. Cover you

Before the information calculation, bit complement should be performed. If the length of the information after the complement is set as LEN(bit), then LEN%512 = 448(bit), that is, the data is extended to K * 512 + 448(bit). So K * 64+56(byte), K is an integer. A complement operation is always performed, even if the length of the message before the complement is left at 448 for 512. Specific fill operation: fill 1 1, and then fill 0 to meet the above requirements. In total, at least 1bit should be supplemented, and at most 512bit should be supplemented.

2. Add the information length to the tail

Represent the original length of the input information as a number of 64-bit, and add it to the result of the previous step (on a 32-bit machine, the 64-bit will be represented in two words and low in front). In rare cases where b is greater than 2^64, the high bits of b are truncated and only the low 64 bits of b are used. After the above two steps, the data is filled with multiples of 512(bit). That is, the length of the data is an integer multiple of 16 words (32byte). At this time, the data is expressed as: M[0... N-1] where N is a multiple of 16.

3. Initialize the cache

With a four word buffer (A B, C, D) to calculate the message digest, A, B, C, D 32-bit registers, initialization using the said 106 hexadecimal number, pay attention to the low byte in front: word A: 01 23 45 67 word B: 89 ab cd ef word C: fe dc word 98 word D: 76 54 32 10

4. The conversion

First of all, four auxiliary functions are defined. The input of each function is 3 32-bit words, and the output is 1 32-bit word: F(X,Y,Z) = XY v (X) Z G(X,Y,Z) = XZ v (Z) H(X,Y,Z) = X xor Y xor Z I(X,Y,Z) = Y xor (X v not(Z))

``````
FF(a,b,c,d,Mj,s,ti ) said  a = b + ((a + F(b,c,d) + Mj + ti) << s)
GG(a,b,c,d,Mj,s,ti ) said  a = b + ((a + G(b,c,d) + Mj + ti) << s)
HH(a,b,c,d,Mj,s,ti ) said  a = b + ((a + H(b,c,d) + Mj + ti) << s)
Ⅱ ( a,b,c,d,Mj,s,ti ) said  a = b + ((a + I(b,c,d) + Mj + ti) << s)``````

The four rounds (64 steps) are:

1 round

FF (a b, c d, M0, 7, 0) xd76aa478 FF (d a, b, c, M1, 12, 0 xe8c7b756) FF (c d, a b, M2, 17, 0 x242070db) FF (b c, d, a, M3, 22, 0 xc1bdceee) FF (a b, c d, M4, 7, 0) xf57c0faf FF (d a, b, c, M5, 12, 0 x4787c62a) FF (c d, a b, M6, 17, 0 xa8304613) FF (b c, d, a, M7, 22, 0 xfd469501) FF (a b, c d, M8, 7, 0) x698098d8 FF (d a, b, c, M9, 12, 0 x8b44f7af) FF (c d, a b, M10, 17, 0 xffff5bb1) FF (b c, d, a, M11, 22, 0 x895cd7be) FF (a b, c d, M12, 7, 0) x6b901122 FF (d a, b, c, M13, 12, 0 xfd987193) FF (c d, a b, M14, 17, 0 xa679438e) FF (b c, d, a, M15, 22, 0 x49b40821)

Second round

GG (a b, c d, M1, 5, 0 xf61e2562) GG (d a, b, c, M6, 9, 0 xc040b340) GG (c d, a b, M11, 14, 0 x265e5a51) GG (b c, d, a, M0, 20, 0 xe9b6c7aa) GG (a b, c d, M5, 5, 0 xd62f105d) GG (d a, b, c, M10, 9, 0 x02441453) GG (c d, a b, M15, 14, 0 xd8a1e681) GG (b c, d, a, M4, 20, 0 xe7d3fbc8) GG (a b, c d, M9, 5, 0 x21e1cde6) GG (d a, b, c, M14, 9, 0 xc33707d6) GG (c d, a b, M3, 14, 0 xf4d50d87) GG (b c, d, a, M8, 20, 0 x455a14ed) GG (a b, c d, M13, 5, 0 xa9e3e905) GG (d a, b, c, M2, 9, 0 xfcefa3f8) GG (c d, a b, M7, 14, 0 x676f02d9) GG (b c, d, a, M12, 20, 0 x8d2a4c8a)

The third wheel

HH (a b, c d, M5, 4, 0 xfffa3942 HH (d a, b, c, M8, 11, 0 x8771f681) HH (c d, a b, M11, 16, 0 x6d9d6122) HH (b c, d, a, M14, 23, 0 xfde5380c) HH (a b, c d, M1, 4, 0 xa4beea44 HH (d a, b, c, M4, 11, 0 x4bdecfa9) HH (c d, a b, M7, 16, 0 xf6bb4b60) HH (b c, d, a, M10, 23, 0 xbebfbc70) HH (a b, c d, M13, 4, 0 x289b7ec6 HH (d a, b, c, M0, 11, 0 xeaa127fa) HH (c d, a b, M3, 16, 0 xd4ef3085) HH (b c, d, a, M6, 23, 0 x04881d05) HH (a b, c d, M9, 4, 0 xd9d4d039 HH (d a, b, c, M12, 11, 0 xe6db99e5) HH (c d, a b, M15, 16, 0 x1fa27cf8) HH (b c, d, a, M2, 23, 0 xc4ac5665)

The fourth round of

Ⅱ (a b, c d, M0, 6, 0 xf4292244) Ⅱ (d a, b, c, M7, 10, 0 x432aff97) Ⅱ (c d, a, b, M14, 15, 0 xab9423a7) Ⅱ (b c, d a, M5, 21, 0 xfc93a039) Ⅱ (a b, c, d, M12, 6, 0 x655b59c3) Ⅱ (d a, b c, M3, 10, 0 x8f0ccc92) Ⅱ (c d, a, b, M10, 15, 0 xffeff47d) Ⅱ (b c, d a, M1, 21, 0 x85845dd1) Ⅱ (a b, c, d, M8, 6, 0 x6fa87e4f) Ⅱ (d a, b c, M15, 10, 0 xfe2ce6e0) Ⅱ (c d, a, b, M6, 15, 0 xa3014314) Ⅱ (b c, d a, M13, 21, 0 x4e0811a1) Ⅱ (a b, c, d, M4, 6, 0 xf7537e82) Ⅱ (d a, b c, M11, 10, 0 xbd3af235) Ⅱ (c d, a, b, M2, 15, 0 x2ad7d2bb) Ⅱ (b c, d a, M9, 21, 0 xeb86d391)

The following is the concrete implementation of MD5 algorithm

``````
#ifndef MD5_H
#define MD5_H

typedef struct
{
unsigned int count;
unsigned int state;
unsigned char buffer;
}MD5_CTX;

#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))
#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))

#define FF(a,b,c,d,x,s,ac) { \
a += F(b, c, d) + x + ac; \
a = ROTATE_LEFT(a, s); \
a += b; \
}

#define GG(a,b,c,d,x,s,ac) { \
a += G(b, c, d) + x + ac; \
a = ROTATE_LEFT(a, s); \
a += b; \
}

#define HH(a,b,c,d,x,s,ac) { \
a += H(b, c, d) + x + ac; \
a = ROTATE_LEFT(a, s); \
a += b; \
}
#define II(a,b,c,d,x,s,ac) { \
a += I(b, c, d) + x + ac; \
a = ROTATE_LEFT(a, s); \
a += b; \
}

void MD5Init(MD5_CTX *context);
void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputlen);
void MD5Final(MD5_CTX *context, unsigned char digest);
void MD5Transform(unsigned int state, unsigned char block);
void MD5Encode(unsigned char *output, unsigned int *input, unsigned int len);
void MD5Decode(unsigned int *output, unsigned char *input, unsigned int len);

#endif``````

MD5 algorithm implementation file Md5.cpp:

``````
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

// When reverting code, you need to focus on the following eigenvalues
void MD5Init(MD5_CTX *context)
{
context->count = 0;
context->count = 0;
context->state = 0x67452301;
context->state = 0xEFCDAB89;
context->state = 0x10325476;
}

void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputlen)
{
unsigned int i = 0, index = 0, partlen = 0;
index = (context->count >> 3) & 0x3F;
partlen = 64 - index;
context->count += inputlen << 3;
if (context->count < (inputlen << 3))
context->count++;
context->count += inputlen >> 29;

if (inputlen >= partlen)
{
memcpy(&context->buffer[index], input, partlen);
MD5Transform(context->state, context->buffer);
for (i = partlen; i + 64 <= inputlen; i += 64)
MD5Transform(context->state, &input[i]);
index = 0;
}
else
{
i = 0;
}
memcpy(&context->buffer[index], &input[i], inputlen - i);
}

void MD5Final(MD5_CTX *context, unsigned char digest)
{
unsigned int index = 0, padlen = 0;
unsigned char bits;
index = (context->count >> 3) & 0x3F;
padlen = (index < 56) ? (56 - index) : (120 - index);
MD5Encode(bits, context->count, 8);
MD5Update(context, bits, 8);
MD5Encode(digest, context->state, 16);
}

void MD5Encode(unsigned char *output, unsigned int *input, unsigned int len)
{
unsigned int i = 0, j = 0;
while (j < len)
{
output[j] = input[i] & 0xFF;
output[j + 1] = (input[i] >> 8) & 0xFF;
output[j + 2] = (input[i] >> 16) & 0xFF;
output[j + 3] = (input[i] >> 24) & 0xFF;
i++;
j += 4;
}
}

void MD5Decode(unsigned int *output, unsigned char *input, unsigned int len)
{
unsigned int i = 0, j = 0;
while (j < len)
{
output[i] = (input[j]) |
(input[j + 1] << 8) |
(input[j + 2] << 16) |
(input[j + 3] << 24);
i++;
j += 4;
}
}

void MD5Transform(unsigned int state, unsigned char block)
{
unsigned int a = state;
unsigned int b = state;
unsigned int c = state;
unsigned int d = state;
unsigned int x;

MD5Decode(x, block, 64);
FF(a, b, c, d, x, 7, 0xd76aa478);
FF(d, a, b, c, x, 12, 0xe8c7b756);
FF(c, d, a, b, x, 17, 0x242070db);
FF(b, c, d, a, x, 22, 0xc1bdceee);
FF(a, b, c, d, x, 7, 0xf57c0faf);
FF(d, a, b, c, x, 12, 0x4787c62a);
FF(c, d, a, b, x, 17, 0xa8304613);
FF(b, c, d, a, x, 22, 0xfd469501);
FF(a, b, c, d, x, 7, 0x698098d8);
FF(d, a, b, c, x, 12, 0x8b44f7af);
FF(c, d, a, b, x, 17, 0xffff5bb1);
FF(b, c, d, a, x, 22, 0x895cd7be);
FF(a, b, c, d, x, 7, 0x6b901122);
FF(d, a, b, c, x, 12, 0xfd987193);
FF(c, d, a, b, x, 17, 0xa679438e);
FF(b, c, d, a, x, 22, 0x49b40821);

GG(a, b, c, d, x, 5, 0xf61e2562);
GG(d, a, b, c, x, 9, 0xc040b340);
GG(c, d, a, b, x, 14, 0x265e5a51);
GG(b, c, d, a, x, 20, 0xe9b6c7aa);
GG(a, b, c, d, x, 5, 0xd62f105d);
GG(d, a, b, c, x, 9, 0x2441453);
GG(c, d, a, b, x, 14, 0xd8a1e681);
GG(b, c, d, a, x, 20, 0xe7d3fbc8);
GG(a, b, c, d, x, 5, 0x21e1cde6);
GG(d, a, b, c, x, 9, 0xc33707d6);
GG(c, d, a, b, x, 14, 0xf4d50d87);
GG(b, c, d, a, x, 20, 0x455a14ed);
GG(a, b, c, d, x, 5, 0xa9e3e905);
GG(d, a, b, c, x, 9, 0xfcefa3f8);
GG(c, d, a, b, x, 14, 0x676f02d9);
GG(b, c, d, a, x, 20, 0x8d2a4c8a);

HH(a, b, c, d, x, 4, 0xfffa3942);
HH(d, a, b, c, x, 11, 0x8771f681);
HH(c, d, a, b, x, 16, 0x6d9d6122);
HH(b, c, d, a, x, 23, 0xfde5380c);
HH(a, b, c, d, x, 4, 0xa4beea44);
HH(d, a, b, c, x, 11, 0x4bdecfa9);
HH(c, d, a, b, x, 16, 0xf6bb4b60);
HH(b, c, d, a, x, 23, 0xbebfbc70);
HH(a, b, c, d, x, 4, 0x289b7ec6);
HH(d, a, b, c, x, 11, 0xeaa127fa);
HH(c, d, a, b, x, 16, 0xd4ef3085);
HH(b, c, d, a, x, 23, 0x4881d05);
HH(a, b, c, d, x, 4, 0xd9d4d039);
HH(d, a, b, c, x, 11, 0xe6db99e5);
HH(c, d, a, b, x, 16, 0x1fa27cf8);
HH(b, c, d, a, x, 23, 0xc4ac5665);

II(a, b, c, d, x, 6, 0xf4292244);
II(d, a, b, c, x, 10, 0x432aff97);
II(c, d, a, b, x, 15, 0xab9423a7);
II(b, c, d, a, x, 21, 0xfc93a039);
II(a, b, c, d, x, 6, 0x655b59c3);
II(d, a, b, c, x, 10, 0x8f0ccc92);
II(c, d, a, b, x, 15, 0xffeff47d);
II(b, c, d, a, x, 21, 0x85845dd1);
II(a, b, c, d, x, 6, 0x6fa87e4f);
II(d, a, b, c, x, 10, 0xfe2ce6e0);
II(c, d, a, b, x, 15, 0xa3014314);
II(b, c, d, a, x, 21, 0x4e0811a1);
II(a, b, c, d, x, 6, 0xf7537e82);
II(d, a, b, c, x, 10, 0xbd3af235);
II(c, d, a, b, x, 15, 0x2ad7d2bb);
II(b, c, d, a, x, 21, 0xeb86d391);
state += a;
state += b;
state += c;
state += d;
} ``````

Call test of MD5 algorithm:

``````
int _tmain(int argc, _TCHAR* argv[])
{

int i;
unsigned char decrypt;

MD5_CTX md5;

MD5Init(&md5);
MD5Update(&md5, encrypt, strlen((char *)encrypt));
MD5Final(&md5, decrypt);

//Md5 The encrypted 32 A result
printf(" Before the encryption :%s\n encrypted 16 position :", encrypt);
for (i = 4; i<12; i++)
{
printf("%02x", decrypt[i]);
}

//Md5 The encrypted 32 A result
printf("\n Before the encryption :%s\n encrypted 32 position :", encrypt);
for (i = 0; i<16; i++)
{
printf("%02x", decrypt[i]);
}

getchar();

return 0;
}``````