MD5 algorithm implementation

MD5 algorithm implementation

1. MD5 password protection

MD5 is often used for data compression because of its low collision, especially for password protection. Because it is irreversible, the ciphertext obtained after plaintext password encryption cannot be deduced from the original text, and the verification password can be converted to the MD5 value encrypted by the verification password, so as long as the MD5 value of the password is stored in the database, it needs to be verified At this time, only the MD5 value of the input is required to be compared with the database content to see if it is consistent, which does not reveal user information and is almost impossible to make mistakes.

Second, the MD5 algorithm process

1. Process the input string, add a number of bits "100...000" after the whole string (must add at least one bit 1), and add an extra 64 bits at the end to represent the length of the string. It is then divided into L groups of substrings of length 512.

2. Compress the above-mentioned L substrings with a length of 512 bits as a series of compressions, and the result of each step will be used as the input of the next step.

3. The compression process is divided into four different functions F, G, H, I, and each function is iterated 16 times, so for each input substring, 64 rounds of iterations are required.

4. Each compression function will input four 32-bit numbers A, B, C, D in each round, and these four numbers need to be additionally stored in a string CV of length 128. These four numbers have fixed initial values. The variable T is taken as another input, which is related to the number of iterations. Another input variable is S, which can be obtained by looking up the table. As for the input 512-bit substring, it will first be divided into 16 32-bit strings, expressed as an array of unsigned int size of length 16, and then check a table named X according to the number of rounds i to find the corresponding The number of is used as the subscript, and the element corresponding to the subscript is taken from the array of length 16 as the last input variable of the compression function.

5. After each round of compression, new A, B, C, D outputs are obtained, added to CV, and the order of D, A, B, C is used as the input of the next round.

6. At the end of the iteration, each 512-bit substring will get the final 128-bit CV obtained by adding the A, B, C, and D generated by each round of iterations. This is the final MD5 value we need.

3. C language source code

MD5.c :

The MD5 function can be called directly, passing in two pointers, the former finally points to the MD5 value, and the latter is the string that needs to be compressed.

The F, G, H, and I functions are four round functions respectively.

The H_MD5 function is a circular compression function.

Finally, test the operation of the MD5 function in the main function.

#include <memory.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

unsigned char PADDING[] = {
    128, 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
};

unsigned int F(unsigned int A, unsigned int B, unsigned int C, unsigned int D, unsigned int X, unsigned int T, unsigned int S) {
    A += ((B & C) | (~B & D));
    A += X + T;
    A = ((A << S) | (A >> (32 - S)));
    A += B;
    return A;
}

unsigned int G(unsigned int A, unsigned int B, unsigned int C, unsigned int D, unsigned int X, unsigned int T, unsigned int S) {
    A += ((B & D) | (C & ~D));
    A += X + T;
    A = ((A << S) | (A >> (32 - S)));
    A += B;
    return A;
}

unsigned int H(unsigned int A, unsigned int B, unsigned int C, unsigned int D, unsigned int X, unsigned int T, unsigned int S) {
    A += (B ^ C ^ D);
    A += X + T;
    A = ((A << S) | (A >> (32 - S)));
    A += B;
    return A;
}

unsigned int I(unsigned int A, unsigned int B, unsigned int C, unsigned int D, unsigned int X, unsigned int T, unsigned int S) {
    A += (C ^ (B | ~D));
    A += X + T;
    A = ((A << S) | (A >> (32 - S)));
    A += B;
    return A;
}

void H_MD5(unsigned int CV[4], unsigned char input[64]) {
    unsigned int a = CV[0];
    unsigned int b = CV[1];
    unsigned int c = CV[2];
    unsigned int d = CV[3];

    int S[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
    };
    unsigned int *  indexes = (unsigned int *)input;
    unsigned int X[64] = {
        0, 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
        1, 6, 11,  0,  5, 10, 15,  4,  9, 14,  3,  8, 13,  2,  7, 12,
        5, 8, 11, 14,  1,  4,  7, 10, 13,  0,  3,  6,  9, 12, 15,  2,
        0, 7, 14,  5, 12,  3, 10,  1,  8, 15,  6, 13,  4, 11,  2,  9
    };
    int i;
    for (i = 0; i < 16; i++) {
        unsigned int T = pow(2, 32) * fabs(sin(i + 1));//printf("T:%x s:%d x:%d\n", T, S[i], X[i]);
        a = F(a, b, c, d, indexes[X[i]], T, S[i]);
        int tmp = d;
        d = c;
        c = b;
        b = a;
        a = tmp;
    }
    for (i = 16; i < 32; i++) {
        unsigned int T = pow(2, 32) * fabs(sin(i + 1));//printf("T:%x s:%d x:%d\n", T, S[i], X[i]);
        a = G(a, b, c, d, indexes[X[i]], T, S[i]);
        int tmp = d;
        d = c;
        c = b;
        b = a;
        a = tmp;
    }
    for (i = 32; i < 48; i++) {
        unsigned int T = pow(2, 32) * fabs(sin(i + 1));//printf("T:%x s:%d x:%d\n", T, S[i], X[i]);
        a = H(a, b, c, d, indexes[X[i]], T, S[i]);
        int tmp = d;
        d = c;
        c = b;
        b = a;
        a = tmp;
    }
    for (i = 48; i < 64; i++) {
        unsigned int T = pow(2, 32) * fabs(sin(i + 1));//printf("T:%x s:%d x:%d\n", T, S[i], X[i]);
        a = I(a, b, c, d, indexes[X[i]], T, S[i]);
        int tmp = d;
        d = c;
        c = b;
        b = a;
        a = tmp;
    }
    CV[0] += a;
    CV[1] += b;
    CV[2] += c;
    CV[3] += d;
}

void MD5(unsigned char * cypher, unsigned char * plain) {
    unsigned int CV[4];
    unsigned int Buffer[16];
    CV[0] = 0x67452301;
    CV[1] = 0xEFCDAB89;
    CV[2] = 0x98BADCFE;
    CV[3] = 0x10325476;
    int i = 0;
    for (i = 0; i + 64 <= strlen(plain); i += 64) {
        H_MD5(CV, plain + i);
    }
    int end = i;
    memcpy((unsigned char*)Buffer, plain + end, strlen(plain) - end);

    if (strlen(plain) - end < 56) {
        memcpy((unsigned char*)Buffer + strlen(plain) - end, PADDING, 56 - (strlen(plain) - end));
    } else {
        memcpy((unsigned char*)Buffer + strlen(plain) - end, PADDING, 64 - (strlen(plain) - end));
        H_MD5(CV, (unsigned char *)Buffer);
        memcpy((unsigned char*)Buffer, PADDING + 8, 56);
    }
    unsigned long long length = strlen(plain) << 3;
    memcpy((unsigned char*)Buffer + 56, &length, 8);
    H_MD5(CV, (unsigned char *)Buffer);

    unsigned char * tmp = (unsigned char *)CV;
    for (i = 0; i < 16; i++) {
        cypher[i] = tmp[i];
    }
}

int main(int argc, char *argv[]) {
    unsigned char plain[] ="I'm Jack!";
    unsigned char cypher[16];//1137e3b1c91cc53d0886da77f2993a2d

    MD5(cypher, plain);
    printf("Plain  Text: %s\n", plain);
    printf("Cypher Text: ");
    int i;
    for(i = 0; i < 16; i++) {
        printf("%02x", cypher[i]);
    }
    return 0;
}

Fourth, the operation of the algorithm

The image below is a screenshot of the running situation and the printed text.

See that the bottom two lines are "Plain Text: I'm Jack!
Cypher Text: 1137e3b1c91cc53d0886da77f2993a2d".

write picture description here

The following is a screenshot of using online MD5 online encryption as a comparison. The encrypted ciphertext is consistent with the code I wrote in C language, indicating that the MD5 algorithm has been successfully implemented.

write picture description here

T:d76aa478 s:7 x:0
T:e8c7b756 s:12 x:1
T:242070db s:17 x:2
T:c1bdceee s:22 x:3
T:f57c0faf s:7 x:4
T:4787c62a s:12 x:5
T:a8304613 s:17 x:6
T:fd469501 s:22 x:7
T:698098d8 s:7 x:8
T:8b44f7af s:12 x:9
T:ffff5bb1 s:17 x:10
T:895cd7be s:22 x:11
T:6b901122 s:7 x:12
T:fd987193 s:12 x:13
T:a679438e s:17 x:14
T:49b40821 s:22 x:15
T:f61e2562 s:5 x:1
T:c040b340 s:9 x:6
T:265e5a51 s:14 x:11
T:e9b6c7aa s:20 x:0
T:d62f105d s:5 x:5
T:2441453 s:9 x:10
T:d8a1e681 s:14 x:15
T:e7d3fbc8 s:20 x:4
T:21e1cde6 s:5 x:9
T:c33707d6 s:9 x:14
T:f4d50d87 s:14 x:3
T:455a14ed s:20 x:8
T:a9e3e905 s:5 x:13
T:fcefa3f8 s:9 x:2
T:676f02d9 s:14 x:7
T:8d2a4c8a s:20 x:12
T:fffa3942 s:4 x:5
T:8771f681 s:11 x:8
T:6d9d6122 s:16 x:11
T:fde5380c s:23 x:14
T:a4beea44 s:4 x:1
T:4bdecfa9 s:11 x:4
T:f6bb4b60 s:16 x:7
T:bebfbc70 s:23 x:10
T:289b7ec6 s:4 x:13
T:eaa127fa s:11 x:0
T:d4ef3085 s:16 x:3
T:4881d05 s:23 x:6
T:d9d4d039 s:4 x:9
T:e6db99e5 s:11 x:12
T:1fa27cf8 s:16 x:15
T:c4ac5665 s:23 x:2
T:f4292244 s:6 x:0
T:432aff97 s:10 x:7
T:ab9423a7 s:15 x:14
T:fc93a039 s:21 x:5
T:655b59c3 s:6 x:12
T:8f0ccc92 s:10 x:3
T:ffeff47d s:15 x:10
T:85845dd1 s:21 x:1
T:6fa87e4f s:6 x:8
T:fe2ce6e0 s:10 x:15
T:a3014314 s:15 x:6
T:4e0811a1 s:21 x:13
T:f7537e82 s:6 x:4
T:bd3af235 s:10 x:11
T:2ad7d2bb s:15 x:2
T:eb86d391 s:21 x:9
Plain Text: I’m Jack!
Cypher Text: 1137e3b1c91cc53d0886da77f2993a2d

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325643225&siteId=291194637