1
1 #include2 #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 #include10 #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 #include2 #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 }