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的相关文档,有兴趣的自己去看下吧

 

posted @ 2025-06-02 12:07  蓝bleu  阅读(29)  评论(0)    收藏  举报