3 * $Id: md5.c,v 1.3 1998/01/12 16:46:11 mdw Exp $
5 * MD-5 secure hash routines
6 * Based on RSA MD-5 code
8 * (c) 1996-1998 Mark Wooding
11 /*----- Licensing notice --------------------------------------------------*
13 * This file is part of `become'
15 * `Become' is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * `Become' is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with `become'; if not, write to the Free Software Foundation,
27 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 /*----- Revision history --------------------------------------------------*
33 * Revision 1.3 1998/01/12 16:46:11 mdw
36 * Revision 1.2 1997/08/04 10:24:23 mdw
37 * Sources placed under CVS control.
39 * Revision 1.1 1997/07/21 13:47:47 mdw
44 /*----- Header files ------------------------------------------------------*/
53 /*----- Define MD-5 transform ---------------------------------------------*/
55 /* --- Low-level nonlinear functions --- */
57 #define f(x,y,z) (((x) & (y)) | ((~x) & (z)))
58 #define g(x,y,z) (((x) & (z)) | ((y) & (~z)))
59 #define h(x,y,z) ((x) ^ (y) ^ (z))
60 #define i(x,y,z) ((y) ^ ((x) | (~z)))
62 #define rol(x,b) (((x) << (b)) | ((x) >> (32-(b))))
64 /* --- Rotations applied at various stages --- */
83 /* --- Higher level nonlinear functions --- */
85 #define ff(a, b, c, d, x, s, m) ( a += f(b, c, d) + x + m, \
86 a = rol(a, s), a += b )
88 #define gg(a, b, c, d, x, s, m) ( a += g(b, c, d) + x + m, \
89 a = rol(a, s), a += b )
91 #define hh(a, b, c, d, x, s, m) ( a += h(b, c, d) + x + m, \
92 a = rol(a, s), a += b )
94 #define ii(a, b, c, d, x, s, m) ( a += i(b, c, d) + x + m, \
95 a = rol(a, s), a += b )
97 /*----- Main code ---------------------------------------------------------*/
99 /* --- @md5__trans@ --- *
101 * Arguments: @uint_32 *v@ = pointer to chaining variables (updated)
102 * @const unsigned char *buf@ = pointer to a 64-byte block
106 * Use: Performs the main MD5 transform on a block of data.
109 static void md5__trans(uint_32
*v
, const unsigned char *buf
)
115 /* --- Initialise my internal registers --- */
117 a
= v
[0], b
= v
[1], c
= v
[2], d
= v
[3];
119 /* --- Turn the buffer into 32-bit words --- */
121 for (i
= 0; i
< 16; i
++)
122 ib
[i
] = load32_l(buf
+ (i
<< 2));
124 /* --- Round one --- */
126 ff(a
, b
, c
, d
, ib
[ 0], S11
, 0xd76aa478); /* 1 */
127 ff(d
, a
, b
, c
, ib
[ 1], S12
, 0xe8c7b756); /* 2 */
128 ff(c
, d
, a
, b
, ib
[ 2], S13
, 0x242070db); /* 3 */
129 ff(b
, c
, d
, a
, ib
[ 3], S14
, 0xc1bdceee); /* 4 */
130 ff(a
, b
, c
, d
, ib
[ 4], S11
, 0xf57c0faf); /* 5 */
131 ff(d
, a
, b
, c
, ib
[ 5], S12
, 0x4787c62a); /* 6 */
132 ff(c
, d
, a
, b
, ib
[ 6], S13
, 0xa8304613); /* 7 */
133 ff(b
, c
, d
, a
, ib
[ 7], S14
, 0xfd469501); /* 8 */
134 ff(a
, b
, c
, d
, ib
[ 8], S11
, 0x698098d8); /* 9 */
135 ff(d
, a
, b
, c
, ib
[ 9], S12
, 0x8b44f7af); /* 10 */
136 ff(c
, d
, a
, b
, ib
[10], S13
, 0xffff5bb1); /* 11 */
137 ff(b
, c
, d
, a
, ib
[11], S14
, 0x895cd7be); /* 12 */
138 ff(a
, b
, c
, d
, ib
[12], S11
, 0x6b901122); /* 13 */
139 ff(d
, a
, b
, c
, ib
[13], S12
, 0xfd987193); /* 14 */
140 ff(c
, d
, a
, b
, ib
[14], S13
, 0xa679438e); /* 15 */
141 ff(b
, c
, d
, a
, ib
[15], S14
, 0x49b40821); /* 16 */
143 /* --- Round two --- */
145 gg(a
, b
, c
, d
, ib
[ 1], S21
, 0xf61e2562); /* 17 */
146 gg(d
, a
, b
, c
, ib
[ 6], S22
, 0xc040b340); /* 18 */
147 gg(c
, d
, a
, b
, ib
[11], S23
, 0x265e5a51); /* 19 */
148 gg(b
, c
, d
, a
, ib
[ 0], S24
, 0xe9b6c7aa); /* 20 */
149 gg(a
, b
, c
, d
, ib
[ 5], S21
, 0xd62f105d); /* 21 */
150 gg(d
, a
, b
, c
, ib
[10], S22
, 0x02441453); /* 22 */
151 gg(c
, d
, a
, b
, ib
[15], S23
, 0xd8a1e681); /* 23 */
152 gg(b
, c
, d
, a
, ib
[ 4], S24
, 0xe7d3fbc8); /* 24 */
153 gg(a
, b
, c
, d
, ib
[ 9], S21
, 0x21e1cde6); /* 25 */
154 gg(d
, a
, b
, c
, ib
[14], S22
, 0xc33707d6); /* 26 */
155 gg(c
, d
, a
, b
, ib
[ 3], S23
, 0xf4d50d87); /* 27 */
156 gg(b
, c
, d
, a
, ib
[ 8], S24
, 0x455a14ed); /* 28 */
157 gg(a
, b
, c
, d
, ib
[13], S21
, 0xa9e3e905); /* 29 */
158 gg(d
, a
, b
, c
, ib
[ 2], S22
, 0xfcefa3f8); /* 30 */
159 gg(c
, d
, a
, b
, ib
[ 7], S23
, 0x676f02d9); /* 31 */
160 gg(b
, c
, d
, a
, ib
[12], S24
, 0x8d2a4c8a); /* 32 */
162 /* --- Round three --- */
164 hh(a
, b
, c
, d
, ib
[ 5], S31
, 0xfffa3942); /* 33 */
165 hh(d
, a
, b
, c
, ib
[ 8], S32
, 0x8771f681); /* 34 */
166 hh(c
, d
, a
, b
, ib
[11], S33
, 0x6d9d6122); /* 35 */
167 hh(b
, c
, d
, a
, ib
[14], S34
, 0xfde5380c); /* 36 */
168 hh(a
, b
, c
, d
, ib
[ 1], S31
, 0xa4beea44); /* 37 */
169 hh(d
, a
, b
, c
, ib
[ 4], S32
, 0x4bdecfa9); /* 38 */
170 hh(c
, d
, a
, b
, ib
[ 7], S33
, 0xf6bb4b60); /* 39 */
171 hh(b
, c
, d
, a
, ib
[10], S34
, 0xbebfbc70); /* 40 */
172 hh(a
, b
, c
, d
, ib
[13], S31
, 0x289b7ec6); /* 41 */
173 hh(d
, a
, b
, c
, ib
[ 0], S32
, 0xeaa127fa); /* 42 */
174 hh(c
, d
, a
, b
, ib
[ 3], S33
, 0xd4ef3085); /* 43 */
175 hh(b
, c
, d
, a
, ib
[ 6], S34
, 0x04881d05); /* 44 */
176 hh(a
, b
, c
, d
, ib
[ 9], S31
, 0xd9d4d039); /* 45 */
177 hh(d
, a
, b
, c
, ib
[12], S32
, 0xe6db99e5); /* 46 */
178 hh(c
, d
, a
, b
, ib
[15], S33
, 0x1fa27cf8); /* 47 */
179 hh(b
, c
, d
, a
, ib
[ 2], S34
, 0xc4ac5665); /* 48 */
181 /* --- Round four --- */
183 ii(a
, b
, c
, d
, ib
[ 0], S41
, 0xf4292244); /* 49 */
184 ii(d
, a
, b
, c
, ib
[ 7], S42
, 0x432aff97); /* 50 */
185 ii(c
, d
, a
, b
, ib
[14], S43
, 0xab9423a7); /* 51 */
186 ii(b
, c
, d
, a
, ib
[ 5], S44
, 0xfc93a039); /* 52 */
187 ii(a
, b
, c
, d
, ib
[12], S41
, 0x655b59c3); /* 53 */
188 ii(d
, a
, b
, c
, ib
[ 3], S42
, 0x8f0ccc92); /* 54 */
189 ii(c
, d
, a
, b
, ib
[10], S43
, 0xffeff47d); /* 55 */
190 ii(b
, c
, d
, a
, ib
[ 1], S44
, 0x85845dd1); /* 56 */
191 ii(a
, b
, c
, d
, ib
[ 8], S41
, 0x6fa87e4f); /* 57 */
192 ii(d
, a
, b
, c
, ib
[15], S42
, 0xfe2ce6e0); /* 58 */
193 ii(c
, d
, a
, b
, ib
[ 6], S43
, 0xa3014314); /* 59 */
194 ii(b
, c
, d
, a
, ib
[13], S44
, 0x4e0811a1); /* 60 */
195 ii(a
, b
, c
, d
, ib
[ 4], S41
, 0xf7537e82); /* 61 */
196 ii(d
, a
, b
, c
, ib
[11], S42
, 0xbd3af235); /* 62 */
197 ii(c
, d
, a
, b
, ib
[ 2], S43
, 0x2ad7d2bb); /* 63 */
198 ii(b
, c
, d
, a
, ib
[ 9], S44
, 0xeb86d391); /* 64 */
200 /* --- Update the context --- */
202 v
[0] += a
, v
[1] += b
, v
[2] += c
, v
[3] += d
;
205 /* --- @md5_trans@ --- *
207 * Arguments: @unsigned char *v@ = pointer to chaining block (updated)
208 * @const unsigned char *buf@ = pointer to input buffer
212 * Use: Performs the MD5 transformation on a chunk of data. This may
213 * be useful for using MD5 in MDC-type cipher constructions.
216 void md5_trans(unsigned char *v
, const unsigned char *buf
)
220 vv
[0] = load32_l(v
+ 0);
221 vv
[1] = load32_l(v
+ 4);
222 vv
[2] = load32_l(v
+ 8);
223 vv
[3] = load32_l(v
+ 12);
225 store32_l(v
+ 0, vv
[0]);
226 store32_l(v
+ 4, vv
[1]);
227 store32_l(v
+ 8, vv
[2]);
228 store32_l(v
+ 12, vv
[3]);
231 /* --- @md5_buffer@ --- *
233 * Arguments: @md5 *m@ = pointer to an MD5 context
234 * @const void *buff@ = pointer to buffer of data
235 * @size_t size@ = size of buffer
239 * Use: Hashes the buffer of data. You can call @md5_buffer@
240 * lots of times during an MD5 job, to allow big files to be
241 * split into little ones.
244 void md5_buffer(md5
*m
, const void *buff
, size_t size
)
247 const unsigned char *b
= buff
;
250 /* --- Maybe there's some data already in the buffer --- */
252 if (x
= m
->size
& 63, x
) {
255 memcpy(x
+ m
->buf
, b
, s
);
259 memcpy(x
+ m
->buf
, b
, y
);
260 md5__trans(m
->val
, m
->buf
);
264 /* --- Now do whole buffers-full --- */
267 md5__trans(m
->val
, b
);
271 /* --- Tidy up the tail end --- */
274 memcpy(m
->buf
, b
, s
);
278 /* --- @md5_key@ --- *
280 * Arguments: @md5 *m@ = pointer to an MD5 context
281 * @const unsigned char *k@ = pointer to a 4-word `key'
285 * Use: Initialises a context buffer, with a chosen initialisation
286 * string (instead of the standard MD5 value). This allows you
287 * to use NMAC message authentication, should the urge take you.
290 void md5_key(md5
*m
, const unsigned char *k
)
293 m
->val
[0] = load32_l(k
+ 0);
294 m
->val
[0] = load32_l(k
+ 4);
295 m
->val
[0] = load32_l(k
+ 8);
296 m
->val
[0] = load32_l(k
+ 12);
299 /* --- @md5_init@ --- *
301 * Arguments: @md5 *m@ = pointer to an MD5 context
305 * Use: Initialises the context buffer, so that you can do an
309 void md5_init(md5
*m
)
312 m
->val
[0] = 0x67452301;
313 m
->val
[1] = 0xefcdab89;
314 m
->val
[2] = 0x98badcfe;
315 m
->val
[3] = 0x10325476;
318 /* --- @md5_final@ --- *
320 * Arguments: @md5 *m@ = pointer to context buffer
321 * @unsigned char *v@ = where to store the value
325 * Use: Finalises an MD5 buffer, so that you can use the result.
328 void md5_final(md5
*m
, unsigned char *v
)
332 /* --- Pad out the block --- */
335 const static unsigned char pad
[64] = { 0x80 };
336 int p
= m
->size
& 63;
337 p
= (p
< 56) ?
(p
= 56 - p
) : (p
= 120 - p
);
338 md5_buffer(m
, pad
, p
);
341 /* --- Append the length --- */
346 store32_l(b
+ 0, s
<< 3);
347 store32_l(b
+ 4, s
>> 29);
351 /* --- Write out the value --- */
354 store32_l(v
+ 0, m
->val
[0]);
355 store32_l(v
+ 4, m
->val
[1]);
356 store32_l(v
+ 8, m
->val
[2]);
357 store32_l(v
+ 12, m
->val
[3]);
361 /*----- Test driver -------------------------------------------------------*/
365 int main(int argc
, char *argv
[])
367 if (argc
> 1 && strcmp(argv
[1], "-x") == 0) {
373 "", { 0xd98c1dd4, 0x04b2008f, 0x980980e9, 0x7e42f8ec },
374 "a", { 0xb975c10c, 0xa8b6f1c0, 0xe299c331, 0x61267769 },
375 "abc", { 0x98500190, 0xb04fd23c, 0x7d3f96d6, 0x727fe128 },
376 "message digest", { 0x7d696bf9, 0x8d93b77c, 0x312f5a52, 0xd061f1aa },
377 "abcdefghijklmnopqrstuvwxyz",
378 { 0xd7d3fcc3, 0x00e49261, 0x6c49fb7d, 0x3be167ca },
379 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
380 { 0x98ab74d1, 0xf5d977d2, 0x2c1c61a5, 0x9f9d419f },
381 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
382 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
383 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
384 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
385 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
386 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
387 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
388 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
389 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
390 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
391 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
392 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
393 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
394 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
395 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
396 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
397 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
398 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
399 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
400 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
401 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
402 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
403 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n",
404 { 0xbaa7652b, 0x5e10cd4a, 0xde9acbf2, 0xfa0b9fbd }
406 int steptbl
[] = { 3, 18, 32, 37, 63, 64, 65, 256, 1024, -1 };
414 for (i
= 0; i
< sizeof(table
) / sizeof(table
[0]); i
++) {
415 sz
= strlen(table
[i
].string
);
416 for (j
= 0; steptbl
[j
] < sz
&& steptbl
[j
] != -1; j
++) {
420 for (a
= sz
; a
> d
; a
-= d
) {
421 md5_buffer(&m
, p
, d
);
424 md5_buffer(&m
, p
, a
);
426 if (m
.val
[0] != table
[i
].md
[0] ||
427 m
.val
[1] != table
[i
].md
[1] ||
428 m
.val
[2] != table
[i
].md
[2] ||
429 m
.val
[3] != table
[i
].md
[3]) {
430 printf("!!! bad value, string == `%s', step size == %i\n"
431 "!!! expected %08lx-%08lx-%08lx-%08lx, found "
432 "%08lx-%08lx-%08lx-%08lx\n\n",
434 (unsigned long)table
[i
].md
[0],
435 (unsigned long)table
[i
].md
[1],
436 (unsigned long)table
[i
].md
[2],
437 (unsigned long)table
[i
].md
[3],
438 (unsigned long)m
.val
[0],
439 (unsigned long)m
.val
[1],
440 (unsigned long)m
.val
[2],
441 (unsigned long)m
.val
[3]);
446 md5_buffer(&m
, table
[i
].string
, sz
);
448 if (m
.val
[0] != table
[i
].md
[0] ||
449 m
.val
[1] != table
[i
].md
[1] ||
450 m
.val
[2] != table
[i
].md
[2] ||
451 m
.val
[3] != table
[i
].md
[3]) {
452 printf("!!! bad value, string == `%s', step size == entire string\n"
453 "!!! expected %08lx-%08lx-%08lx-%08lx, found "
454 "%08lx-%08lx-%08lx-%08lx\n\n",
456 (unsigned long)table
[i
].md
[0],
457 (unsigned long)table
[i
].md
[1],
458 (unsigned long)table
[i
].md
[2],
459 (unsigned long)table
[i
].md
[3],
460 (unsigned long)m
.val
[0],
461 (unsigned long)m
.val
[1],
462 (unsigned long)m
.val
[2],
463 (unsigned long)m
.val
[3]);
466 printf("`%s' => %08lx-%08lx-%08lx-%08lx\n",
468 (unsigned long)m
.val
[0],
469 (unsigned long)m
.val
[1],
470 (unsigned long)m
.val
[2],
471 (unsigned long)m
.val
[3]);
483 while (read
= fread(buff
, 1, 4096, stdin
), read
)
484 md5_buffer(&m
, buff
, read
);
487 for (i
= 0; i
< 4; i
++)
488 printf("%02lx%02lx%02lx%02lx",
489 (unsigned long)( (m
.val
[i
] & 0x000000FF) >> 0 ),
490 (unsigned long)( (m
.val
[i
] & 0x0000FF00) >> 8 ),
491 (unsigned long)( (m
.val
[i
] & 0x00FF0000) >> 16 ),
492 (unsigned long)( (m
.val
[i
] & 0xFF000000) >> 24 ));
502 /*----- That's all, folks -------------------------------------------------*/