MD5算法的C语言实现

1

  1 #include 
  2 #include 
  3 #include 
  4 #include <string.h>
  5 #include 
  6 #include "md5.h"
  7 
  8 #ifdef __cplusplus
  9 extern "C" {
 10 #endif
 11 
 12 #define ROTATELEFT(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
 13 
 14 #define TO_HEX_FMT_L "%02x"
 15 #define TO_HEX_FMT_U "%02X"
 16 
 17 /**
 18  * @desc: convert message and mes_bkp string into integer array and store them in w 
 19  */
 20 static void md5_process_part1(uint32_t *w, const char *message, uint32_t *pos, uint32_t mes_len, const unsigned char *mes_bkp)
 21 {
 22     uint32_t i; // used in for loop
 23 
 24     for(i = 0; i <= 15; i++)
 25     {
 26         int32_t count = 0;
 27         while(*pos < mes_len && count <= 24)
 28         {
 29             w[i] += (((uint32_t)message[*pos]) << count);
 30             (*pos)++;
 31             count += 8;
 32         }
 33         while(count <= 24)
 34         {
 35             w[i] += (((uint32_t)mes_bkp[*pos - mes_len]) << count);
 36             (*pos)++;
 37             count += 8;
 38         }
 39     }
 40 }
 41 
 42 /**
 43  * @desc: start encryption based on w
 44  */
 45 static void md5_process_part2(uint32_t abcd[4], uint32_t *w, const uint32_t k[64], const uint32_t s[64])
 46 {
 47     uint32_t i; // used in for loop
 48 
 49     uint32_t a = abcd[0];
 50     uint32_t b = abcd[1];
 51     uint32_t c = abcd[2];
 52     uint32_t d = abcd[3];
 53     uint32_t f = 0;
 54     uint32_t g = 0;
 55 
 56     for(i = 0; i < 64; i++)
 57     {
 58         if(i >= 0 && i <= 15)
 59         {
 60             f = (b & c) | ((~b) & d);
 61             g = i;
 62         }else if(i >= 16 && i <= 31)
 63         {
 64             f = (d & b) | ((~d) & c);
 65             g = (5 * i + 1) % 16;
 66         }else if(i >= 32 && i <= 47)
 67         {
 68             f = b ^ c ^ d;
 69             g = (3 * i + 5) % 16;
 70         }else if(i >= 48 && i <= 63)
 71         {
 72             f = c ^ (b | (~d));
 73             g = (7 * i) % 16;
 74         }
 75         uint32_t temp = d;
 76         d = c;
 77         c = b;
 78         b = ROTATELEFT((a + f + k[i] + w[g]), s[i]) + b;
 79         a = temp;
 80     }
 81 
 82     abcd[0] += a;
 83     abcd[1] += b;
 84     abcd[2] += c;
 85     abcd[3] += d;
 86 }
 87 
 88 /**
 89  * @desc: format the output, convert numbers to hexdecimal string and store them in result
 90  */
 91 static void format_output(char *result, size_t size, uint32_t *abcd, uint32_t flag)
 92 {
 93     uint32_t i; // used in for loop
 94     
 95     memset(result, 0, size);
 96 
 97     uint32_t ptr = 0;
 98     for(i = 0; i < 4; i++)
 99     {
100         ptr += snprintf(result + ptr, size - ptr, (flag == 0)?TO_HEX_FMT_U:TO_HEX_FMT_L, (abcd[i] & 0x000000FF));
101         ptr += snprintf(result + ptr, size - ptr, (flag == 0)?TO_HEX_FMT_U:TO_HEX_FMT_L, (abcd[i] & 0x0000FF00) >> 8 );
102         ptr += snprintf(result + ptr, size - ptr, (flag == 0)?TO_HEX_FMT_U:TO_HEX_FMT_L, (abcd[i] & 0x00FF0000) >> 16);
103         ptr += snprintf(result + ptr, size - ptr, (flag == 0)?TO_HEX_FMT_U:TO_HEX_FMT_L, (abcd[i] & 0xFF000000) >> 24);
104     }
105 }
106 
107 
108 /**
109  * @input: result -- store the calculation result
110  *         size   -- size of result. Make sure it's at least 33 
111  *                   since the result is a 32-byte hexdecimal string.
112  *         message-- string to be encrypted
113  *         flag   -- 0 means upper case output, 1 means lower case output
114  * @return: 0 -- success
115  *          1 -- result size less than 33
116  *          2 -- calloc failed
117  */
118 int32_t cal_md5(char *result, size_t size, const char *message, uint32_t flag){
119     if (result == NULL || size < 33)
120     {
121         return 1;
122     }
123     
124     uint32_t *w = (uint32_t *)calloc(16, sizeof(uint32_t));
125     if(w == NULL)
126     {
127         return 2;
128     }
129 
130     uint32_t i; // used in for loop
131 
132     uint32_t mes_len = strlen(message);
133     uint32_t looptimes = (mes_len + 8) / 64 + 1;
134     uint32_t abcd[] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476};
135 
136     const uint32_t k[]={
137         0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,
138         0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8,
139         0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,
140         0xa679438e,0x49b40821,0xf61e2562,0xc040b340,0x265e5a51,
141         0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,
142         0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,
143         0xfcefa3f8,0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,
144         0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,
145         0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,
146         0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,0xf4292244,
147         0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,
148         0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,
149         0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391
150     };
151 
152     const uint32_t s[]={
153         7,12,17,22,7,12,17,22,7,12,17,22,7,
154         12,17,22,5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
155         4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,6,10,
156         15,21,6,10,15,21,6,10,15,21,6,10,15,21
157     };
158 
159     uint32_t pos = 0; // position pointer for message string
160     uint32_t bkp_len = 64 * looptimes - mes_len;
161     unsigned char *bkp_mes = (unsigned char *)calloc(1, bkp_len);
162     if(bkp_mes == NULL)
163     {
164         free(w);
165         return 2;
166     }
167 
168     bkp_mes[0] = (unsigned char)(0x80);
169     uint64_t mes_bit_len = ((uint64_t)mes_len) * 8;
170     for(i = 0; i < 8; i++)
171     {
172         bkp_mes[bkp_len-i-1] = (unsigned char)((mes_bit_len & (0x00000000000000FF << (8 * (7 - i)))) >> (8 * (7 - i)));
173     }
174     
175     for(i = 0; i < looptimes; i++)
176     {
177         memset(w, 0, 16 * sizeof(uint32_t));
178         
179         md5_process_part1(w, message, &pos, mes_len, bkp_mes); // compute w
180         
181         md5_process_part2(abcd, w, k, s); // calculate md5 and store the result in abcd
182     }
183     
184     free(w);
185     free(bkp_mes);
186 
187     format_output(result, size, abcd, flag);
188 
189     return 0;
190 }
191 
192 #ifdef __cplusplus
193 }
194 #endif

 

2

 1 /**
 2  * @author Horst Xu
 3  * @date 2015-07-10
 4  * @contact [email protected]
 5  */
 6 #ifndef __MD5_H__
 7 #define __MD5_H__
 8 
 9 #include 
10 #include 
11 
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15 
16 /**
17  * @input: result -- store the calculation result
18  *         size   -- size of result. Make sure it's at least 33 
19  *                   since the result is a 32-byte hexdecimal string.
20  *         message-- string to be encrypted
21  *         flag   -- 0 means upper case output, 1 means lower case output
22  * @return: 0 -- success
23  *          1 -- result size less than 33
24  *          2 -- calloc failed
25  */
26 int32_t cal_md5(char *result, size_t size, const char *message, uint32_t flag);
27 
28 #ifdef __cplusplus
29 }
30 #endif
31 
32 #endif //__MD5_H__

 

3

 1 #include 
 2 #include 
 3 #include <string.h>
 4 
 5 #include "md5.h"
 6 
 7 int32_t main(void)
 8 {
 9     char result[41];
10     int32_t ret = -1;
11 
12     //test 1
13     ret = cal_md5(result, sizeof(result), "abcdegfhijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz123", 1);
14     if(ret == 0 && 0 == strncmp(result, "dd2fc541b65e2202d55beae0ecaf6528", strlen(result)))
15     {
16         printf("test 1 successful!\n");
17     }else
18     {
19         printf("test 1 failed!\n");
20     }
21 
22     //test 2
23     ret = cal_md5(result, sizeof(result), "abcdegfhijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz1234", 0);
24     if(ret == 0 && 0 == strncmp(result, "27FF2E8344E7E3F36F9C7E18D0EC82DF", strlen(result)))
25     {
26         printf("test 2 successful!\n");
27     }else
28     {
29         printf("test 2 failed!\n");
30     }
31 
32     //test 3
33     ret = cal_md5(result, sizeof(result), "abcdegfhijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz12345", 0);
34     if(ret == 0 && 0 == strncmp(result, "7A7B1279343946E3A5949BEA1B3BF8AF", strlen(result)))
35     {
36         printf("test 3 successful!\n");
37     }else
38     {
39         printf("test 3 failed!\n");
40     }
41 
42     //test 4
43     ret = cal_md5(result, sizeof(result), "", 1);
44     if(ret == 0 && 0 == strncmp(result, "d41d8cd98f00b204e9800998ecf8427e", strlen(result)))
45     {
46         printf("test 4 successful!\n");
47     }else
48     {
49         printf("test 4 failed!\n");
50     }
51 
52     return 0;
53 }

 

你可能感兴趣的:(MD5算法的C语言实现)