MD5计算实际在干嘛
MD5这校验,一直在用,但是除了知道是个哈希,被王小云院士在坐月子时候笔算破解了以外,就一直不了解其他信息了。最近闲来无事深挖技术债,顺手把这个了解下。
浏览全网没找到正式的MD5规范官方出处,但还好,RFC文档里有他,虽然不是权威发布文档的地方,但其权威性也可以作为我们理解、开发的指导文件了。具体编号是RFC1321
首先MD是Message Digest的缩写,输出的结果是16Bytes,即128bits。
简单概括,他的逻辑就是内部分成4个uint32_t的数据,新数据每16个uint32_t一组(共计64bytes(512bits))加载与原数据做一连串(实际为64次)的计算操作,数据末端按规则补数据到确保是64bytes(512bits)的倍数,将所有数据执行过计算操作后,把4个uint32_t连成一个uint128_t的数据就是最终的MD5值。
然后提几个细节:
1.4个uint32_t a,b,c,d的初始值分别是 0x67452301,0xefcdab89,0x98badcfe,0x10325476
2.每次计算操作为XX(实例为FF,GG,HH,II),核心函数为X(实例为FGHI),前4个输入为原始数据,第5个输入为新数据,第6个输入为左移位数,第7个输入为常数Ti,实际代码见下方
#define XX(a, b, c, d, x, s, ac) \ {(a) += X ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ }
3.计算操作的1-16次核心操作为 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
4.计算操作的17-32次核心操作为 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
5.计算操作的33-48次核心操作为 #define H(x, y, z) ((x) ^ (y) ^ (z))
6.计算操作的49-64次核心操作为 #define I(x, y, z) ((y) ^ ((x) | (~z)))
7.左移是ringbuffer式的移动,不舍弃数据,具体为 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
8.计算操作的64轮中使用到的常数Ti为 4294967296 * abs(sin(i)) 其中4294967296为232;i起始为1,64终止;i为弧度
9.计算操作中每次的abcd输入顺序,移位长度,用到的新数据索引并非循环变换,纯硬定义,想自己实现具体看备忘录文档
10.补位是补0x80 n个0x00 (uint64_t)Message_Length后使得(Message_Length + 9 + n)能被64整除且n最小,也就是n的范围为[0,63],补位字节总数范围为[9,72]个
下面,上代码
1 #ifndef __MD5_H__ 2 #define __MD5_H__ 3 4 /* typedef a 32 bit type */ 5 typedef unsigned long int UINT4; 6 7 /* Data structure for MD5 (Message Digest) computation */ 8 typedef struct { 9 UINT4 i[2]; /* number of _bits_ handled mod 2^64 */ 10 UINT4 buf[4]; /* scratch buffer */ 11 unsigned char in[64]; /* input buffer */ 12 unsigned char digest[16]; /* actual digest after MD5Final call */ 13 } MD5_CTX; 14 15 16 void MD5Init (MD5_CTX* mdContext); 17 void MD5Update (MD5_CTX* mdContext, unsigned char *inBuf, unsigned int inLen); 18 void MD5Final (MD5_CTX* mdContext); 19 20 21 #endif
1 #include "MD5.h" 2 3 static unsigned char PADDING[64] = { 4 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 5 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 6 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 7 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 8 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 9 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 10 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 11 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 12 }; 13 14 /* F, G and H are basic MD5 functions: selection, majority, parity */ 15 #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) 16 #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) 17 #define H(x, y, z) ((x) ^ (y) ^ (z)) 18 #define I(x, y, z) ((y) ^ ((x) | (~z))) 19 20 /* ROTATE_LEFT rotates x left n bits */ 21 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) 22 23 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ 24 /* Rotation is separate from addition to prevent recomputation */ 25 #define FF(a, b, c, d, x, s, ac) \ 26 {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ 27 (a) = ROTATE_LEFT ((a), (s)); \ 28 (a) += (b); \ 29 } 30 #define GG(a, b, c, d, x, s, ac) \ 31 {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ 32 (a) = ROTATE_LEFT ((a), (s)); \ 33 (a) += (b); \ 34 } 35 #define HH(a, b, c, d, x, s, ac) \ 36 {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ 37 (a) = ROTATE_LEFT ((a), (s)); \ 38 (a) += (b); \ 39 } 40 #define II(a, b, c, d, x, s, ac) \ 41 {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ 42 (a) = ROTATE_LEFT ((a), (s)); \ 43 (a) += (b); \ 44 } 45 46 47 48 void MD5Init (MD5_CTX *mdContext) 49 { 50 mdContext->i[0] = mdContext->i[1] = (UINT4)0; 51 52 /* Load magic initialization constants. 53 */ 54 mdContext->buf[0] = (UINT4)0x67452301; 55 mdContext->buf[1] = (UINT4)0xefcdab89; 56 mdContext->buf[2] = (UINT4)0x98badcfe; 57 mdContext->buf[3] = (UINT4)0x10325476; 58 } 59 60 static void Transform (UINT4 *buf, UINT4 *in) 61 { 62 UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; 63 64 /* Round 1 */ 65 #define S11 7 66 #define S12 12 67 #define S13 17 68 #define S14 22 69 FF ( a, b, c, d, in[ 0], S11, 3614090360ul); /* 1 */ 70 FF ( d, a, b, c, in[ 1], S12, 3905402710ul); /* 2 */ 71 FF ( c, d, a, b, in[ 2], S13, 606105819ul); /* 3 */ 72 FF ( b, c, d, a, in[ 3], S14, 3250441966ul); /* 4 */ 73 FF ( a, b, c, d, in[ 4], S11, 4118548399ul); /* 5 */ 74 FF ( d, a, b, c, in[ 5], S12, 1200080426ul); /* 6 */ 75 FF ( c, d, a, b, in[ 6], S13, 2821735955ul); /* 7 */ 76 FF ( b, c, d, a, in[ 7], S14, 4249261313ul); /* 8 */ 77 FF ( a, b, c, d, in[ 8], S11, 1770035416ul); /* 9 */ 78 FF ( d, a, b, c, in[ 9], S12, 2336552879ul); /* 10 */ 79 FF ( c, d, a, b, in[10], S13, 4294925233ul); /* 11 */ 80 FF ( b, c, d, a, in[11], S14, 2304563134ul); /* 12 */ 81 FF ( a, b, c, d, in[12], S11, 1804603682ul); /* 13 */ 82 FF ( d, a, b, c, in[13], S12, 4254626195ul); /* 14 */ 83 FF ( c, d, a, b, in[14], S13, 2792965006ul); /* 15 */ 84 FF ( b, c, d, a, in[15], S14, 1236535329ul); /* 16 */ 85 86 /* Round 2 */ 87 #define S21 5 88 #define S22 9 89 #define S23 14 90 #define S24 20 91 GG ( a, b, c, d, in[ 1], S21, 4129170786ul); /* 17 */ 92 GG ( d, a, b, c, in[ 6], S22, 3225465664ul); /* 18 */ 93 GG ( c, d, a, b, in[11], S23, 643717713ul); /* 19 */ 94 GG ( b, c, d, a, in[ 0], S24, 3921069994ul); /* 20 */ 95 GG ( a, b, c, d, in[ 5], S21, 3593408605ul); /* 21 */ 96 GG ( d, a, b, c, in[10], S22, 38016083ul); /* 22 */ 97 GG ( c, d, a, b, in[15], S23, 3634488961ul); /* 23 */ 98 GG ( b, c, d, a, in[ 4], S24, 3889429448ul); /* 24 */ 99 GG ( a, b, c, d, in[ 9], S21, 568446438ul); /* 25 */ 100 GG ( d, a, b, c, in[14], S22, 3275163606ul); /* 26 */ 101 GG ( c, d, a, b, in[ 3], S23, 4107603335ul); /* 27 */ 102 GG ( b, c, d, a, in[ 8], S24, 1163531501ul); /* 28 */ 103 GG ( a, b, c, d, in[13], S21, 2850285829ul); /* 29 */ 104 GG ( d, a, b, c, in[ 2], S22, 4243563512ul); /* 30 */ 105 GG ( c, d, a, b, in[ 7], S23, 1735328473ul); /* 31 */ 106 GG ( b, c, d, a, in[12], S24, 2368359562ul); /* 32 */ 107 108 /* Round 3 */ 109 #define S31 4 110 #define S32 11 111 #define S33 16 112 #define S34 23 113 HH ( a, b, c, d, in[ 5], S31, 4294588738ul); /* 33 */ 114 HH ( d, a, b, c, in[ 8], S32, 2272392833ul); /* 34 */ 115 HH ( c, d, a, b, in[11], S33, 1839030562ul); /* 35 */ 116 HH ( b, c, d, a, in[14], S34, 4259657740ul); /* 36 */ 117 HH ( a, b, c, d, in[ 1], S31, 2763975236ul); /* 37 */ 118 HH ( d, a, b, c, in[ 4], S32, 1272893353ul); /* 38 */ 119 HH ( c, d, a, b, in[ 7], S33, 4139469664ul); /* 39 */ 120 HH ( b, c, d, a, in[10], S34, 3200236656ul); /* 40 */ 121 HH ( a, b, c, d, in[13], S31, 681279174ul); /* 41 */ 122 HH ( d, a, b, c, in[ 0], S32, 3936430074ul); /* 42 */ 123 HH ( c, d, a, b, in[ 3], S33, 3572445317ul); /* 43 */ 124 HH ( b, c, d, a, in[ 6], S34, 76029189ul); /* 44 */ 125 HH ( a, b, c, d, in[ 9], S31, 3654602809ul); /* 45 */ 126 HH ( d, a, b, c, in[12], S32, 3873151461ul); /* 46 */ 127 HH ( c, d, a, b, in[15], S33, 530742520ul); /* 47 */ 128 HH ( b, c, d, a, in[ 2], S34, 3299628645ul); /* 48 */ 129 130 /* Round 4 */ 131 #define S41 6 132 #define S42 10 133 #define S43 15 134 #define S44 21 135 II ( a, b, c, d, in[ 0], S41, 4096336452ul); /* 49 */ 136 II ( d, a, b, c, in[ 7], S42, 1126891415ul); /* 50 */ 137 II ( c, d, a, b, in[14], S43, 2878612391ul); /* 51 */ 138 II ( b, c, d, a, in[ 5], S44, 4237533241ul); /* 52 */ 139 II ( a, b, c, d, in[12], S41, 1700485571ul); /* 53 */ 140 II ( d, a, b, c, in[ 3], S42, 2399980690ul); /* 54 */ 141 II ( c, d, a, b, in[10], S43, 4293915773ul); /* 55 */ 142 II ( b, c, d, a, in[ 1], S44, 2240044497ul); /* 56 */ 143 II ( a, b, c, d, in[ 8], S41, 1873313359ul); /* 57 */ 144 II ( d, a, b, c, in[15], S42, 4264355552ul); /* 58 */ 145 II ( c, d, a, b, in[ 6], S43, 2734768916ul); /* 59 */ 146 II ( b, c, d, a, in[13], S44, 1309151649ul); /* 60 */ 147 II ( a, b, c, d, in[ 4], S41, 4149444226ul); /* 61 */ 148 II ( d, a, b, c, in[11], S42, 3174756917ul); /* 62 */ 149 II ( c, d, a, b, in[ 2], S43, 718787259ul); /* 63 */ 150 II ( b, c, d, a, in[ 9], S44, 3951481745ul); /* 64 */ 151 152 buf[0] += a; 153 buf[1] += b; 154 buf[2] += c; 155 buf[3] += d; 156 } 157 158 159 void MD5Update (MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen) 160 { 161 UINT4 in[16]; 162 int mdi; 163 unsigned int i, ii; 164 165 /* compute number of bytes mod 64 */ 166 mdi = (int)((mdContext->i[0] >> 3) & 0x3F); 167 168 /* update number of bits */ 169 if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0]) 170 mdContext->i[1]++; 171 mdContext->i[0] += ((UINT4)inLen << 3); 172 mdContext->i[1] += ((UINT4)inLen >> 29); 173 174 while (inLen--) { 175 /* add new character to buffer, increment mdi */ 176 mdContext->in[mdi++] = *inBuf++; 177 178 /* transform if necessary */ 179 if (mdi == 0x40) { 180 for (i = 0, ii = 0; i < 16; i++, ii += 4) 181 in[i] = (((UINT4)mdContext->in[ii + 3]) << 24) | 182 (((UINT4)mdContext->in[ii + 2]) << 16) | 183 (((UINT4)mdContext->in[ii + 1]) << 8) | 184 ((UINT4)mdContext->in[ii]); 185 Transform (mdContext->buf, in); 186 mdi = 0; 187 } 188 } 189 } 190 191 192 void MD5Final (MD5_CTX *mdContext) 193 { 194 UINT4 in[16]; 195 int mdi; 196 unsigned int i, ii; 197 unsigned int padLen; 198 199 /* save number of bits */ 200 in[14] = mdContext->i[0]; 201 in[15] = mdContext->i[1]; 202 203 /* compute number of bytes mod 64 */ 204 mdi = (int)((mdContext->i[0] >> 3) & 0x3F); 205 206 /* pad out to 56 mod 64 */ 207 padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); 208 MD5Update (mdContext, PADDING, padLen); 209 210 /* append length in bits and transform */ 211 for (i = 0, ii = 0; i < 14; i++, ii += 4) 212 in[i] = (((UINT4)mdContext->in[ii + 3]) << 24) | 213 (((UINT4)mdContext->in[ii + 2]) << 16) | 214 (((UINT4)mdContext->in[ii + 1]) << 8) | 215 ((UINT4)mdContext->in[ii]); 216 Transform (mdContext->buf, in); 217 218 /* store buffer in digest */ 219 for (i = 0, ii = 0; i < 4; i++, ii += 4) { 220 mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF); 221 mdContext->digest[ii + 1] = 222 (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); 223 mdContext->digest[ii + 2] = 224 (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); 225 mdContext->digest[ii + 3] = 226 (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); 227 } 228 }
目前技术债我就只还到了这程度了,然后为什么那几个计算操作会是非线性就不深入了。至于王小云院士破解MD5的相关文档,有兴趣的自己去看下吧
浙公网安备 33010602011771号