00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include "md5.h"
00041 #include <string.h>
00042
00043 #ifdef TEST
00044
00045
00046
00047
00048
00049 #include <string.h>
00050 main()
00051 {
00052 static const char *const test[7] = {
00053 "",
00054 "945399884.61923487334tuvga",
00055 "abc",
00056 "message digest",
00057 "abcdefghijklmnopqrstuvwxyz",
00058 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
00059
00060 "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
00061 };
00062 int i;
00063
00064 for (i = 0; i < 7; ++i) {
00065 md5_state_t state;
00066 md5_byte_t digest[16];
00067 int di;
00068
00069 md5_init(&state);
00070 md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i]));
00071 md5_finish(&state, digest);
00072 printf("MD5 (\"%s\") = ", test[i]);
00073 for (di = 0; di < 16; ++di)
00074 printf("%02x", digest[di]);
00075 printf("\n");
00076 }
00077 return 0;
00078 }
00079 #endif
00080
00081
00082
00083
00084
00085 #if 0
00086 #include <math.h>
00087 main()
00088 {
00089 int i;
00090 for (i = 1; i <= 64; ++i) {
00091 unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i)));
00092 printf("#define T%d 0x%08lx\n", i, v);
00093 }
00094 return 0;
00095 }
00096 #endif
00097
00098
00099
00100 #define T1 0xd76aa478
00101 #define T2 0xe8c7b756
00102 #define T3 0x242070db
00103 #define T4 0xc1bdceee
00104 #define T5 0xf57c0faf
00105 #define T6 0x4787c62a
00106 #define T7 0xa8304613
00107 #define T8 0xfd469501
00108 #define T9 0x698098d8
00109 #define T10 0x8b44f7af
00110 #define T11 0xffff5bb1
00111 #define T12 0x895cd7be
00112 #define T13 0x6b901122
00113 #define T14 0xfd987193
00114 #define T15 0xa679438e
00115 #define T16 0x49b40821
00116 #define T17 0xf61e2562
00117 #define T18 0xc040b340
00118 #define T19 0x265e5a51
00119 #define T20 0xe9b6c7aa
00120 #define T21 0xd62f105d
00121 #define T22 0x02441453
00122 #define T23 0xd8a1e681
00123 #define T24 0xe7d3fbc8
00124 #define T25 0x21e1cde6
00125 #define T26 0xc33707d6
00126 #define T27 0xf4d50d87
00127 #define T28 0x455a14ed
00128 #define T29 0xa9e3e905
00129 #define T30 0xfcefa3f8
00130 #define T31 0x676f02d9
00131 #define T32 0x8d2a4c8a
00132 #define T33 0xfffa3942
00133 #define T34 0x8771f681
00134 #define T35 0x6d9d6122
00135 #define T36 0xfde5380c
00136 #define T37 0xa4beea44
00137 #define T38 0x4bdecfa9
00138 #define T39 0xf6bb4b60
00139 #define T40 0xbebfbc70
00140 #define T41 0x289b7ec6
00141 #define T42 0xeaa127fa
00142 #define T43 0xd4ef3085
00143 #define T44 0x04881d05
00144 #define T45 0xd9d4d039
00145 #define T46 0xe6db99e5
00146 #define T47 0x1fa27cf8
00147 #define T48 0xc4ac5665
00148 #define T49 0xf4292244
00149 #define T50 0x432aff97
00150 #define T51 0xab9423a7
00151 #define T52 0xfc93a039
00152 #define T53 0x655b59c3
00153 #define T54 0x8f0ccc92
00154 #define T55 0xffeff47d
00155 #define T56 0x85845dd1
00156 #define T57 0x6fa87e4f
00157 #define T58 0xfe2ce6e0
00158 #define T59 0xa3014314
00159 #define T60 0x4e0811a1
00160 #define T61 0xf7537e82
00161 #define T62 0xbd3af235
00162 #define T63 0x2ad7d2bb
00163 #define T64 0xeb86d391
00164
00165 static void
00166 md5_process(md5_state_t *pms, const md5_byte_t *data )
00167 {
00168 md5_word_t
00169 a = pms->abcd[0], b = pms->abcd[1],
00170 c = pms->abcd[2], d = pms->abcd[3];
00171 md5_word_t t;
00172
00173 #ifndef ARCH_IS_BIG_ENDIAN
00174 # define ARCH_IS_BIG_ENDIAN 1
00175 #endif
00176 #if ARCH_IS_BIG_ENDIAN
00177
00178
00179
00180
00181
00182 md5_word_t X[16];
00183 const md5_byte_t *xp = data;
00184 int i;
00185
00186 for (i = 0; i < 16; ++i, xp += 4)
00187 X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
00188
00189 #else
00190
00191
00192
00193
00194
00195 md5_word_t xbuf[16];
00196 const md5_word_t *X;
00197
00198 if (!((data - (const md5_byte_t *)0) & 3)) {
00199
00200 X = (const md5_word_t *)data;
00201 } else {
00202
00203 memcpy(xbuf, data, 64);
00204 X = xbuf;
00205 }
00206 #endif
00207
00208 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
00209
00210
00211
00212
00213 #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
00214 #define SET(a, b, c, d, k, s, Ti)\
00215 t = a + F(b,c,d) + X[k] + Ti;\
00216 a = ROTATE_LEFT(t, s) + b
00217
00218 SET(a, b, c, d, 0, 7, T1);
00219 SET(d, a, b, c, 1, 12, T2);
00220 SET(c, d, a, b, 2, 17, T3);
00221 SET(b, c, d, a, 3, 22, T4);
00222 SET(a, b, c, d, 4, 7, T5);
00223 SET(d, a, b, c, 5, 12, T6);
00224 SET(c, d, a, b, 6, 17, T7);
00225 SET(b, c, d, a, 7, 22, T8);
00226 SET(a, b, c, d, 8, 7, T9);
00227 SET(d, a, b, c, 9, 12, T10);
00228 SET(c, d, a, b, 10, 17, T11);
00229 SET(b, c, d, a, 11, 22, T12);
00230 SET(a, b, c, d, 12, 7, T13);
00231 SET(d, a, b, c, 13, 12, T14);
00232 SET(c, d, a, b, 14, 17, T15);
00233 SET(b, c, d, a, 15, 22, T16);
00234 #undef SET
00235
00236
00237
00238
00239 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
00240 #define SET(a, b, c, d, k, s, Ti)\
00241 t = a + G(b,c,d) + X[k] + Ti;\
00242 a = ROTATE_LEFT(t, s) + b
00243
00244 SET(a, b, c, d, 1, 5, T17);
00245 SET(d, a, b, c, 6, 9, T18);
00246 SET(c, d, a, b, 11, 14, T19);
00247 SET(b, c, d, a, 0, 20, T20);
00248 SET(a, b, c, d, 5, 5, T21);
00249 SET(d, a, b, c, 10, 9, T22);
00250 SET(c, d, a, b, 15, 14, T23);
00251 SET(b, c, d, a, 4, 20, T24);
00252 SET(a, b, c, d, 9, 5, T25);
00253 SET(d, a, b, c, 14, 9, T26);
00254 SET(c, d, a, b, 3, 14, T27);
00255 SET(b, c, d, a, 8, 20, T28);
00256 SET(a, b, c, d, 13, 5, T29);
00257 SET(d, a, b, c, 2, 9, T30);
00258 SET(c, d, a, b, 7, 14, T31);
00259 SET(b, c, d, a, 12, 20, T32);
00260 #undef SET
00261
00262
00263
00264
00265 #define H(x, y, z) ((x) ^ (y) ^ (z))
00266 #define SET(a, b, c, d, k, s, Ti)\
00267 t = a + H(b,c,d) + X[k] + Ti;\
00268 a = ROTATE_LEFT(t, s) + b
00269
00270 SET(a, b, c, d, 5, 4, T33);
00271 SET(d, a, b, c, 8, 11, T34);
00272 SET(c, d, a, b, 11, 16, T35);
00273 SET(b, c, d, a, 14, 23, T36);
00274 SET(a, b, c, d, 1, 4, T37);
00275 SET(d, a, b, c, 4, 11, T38);
00276 SET(c, d, a, b, 7, 16, T39);
00277 SET(b, c, d, a, 10, 23, T40);
00278 SET(a, b, c, d, 13, 4, T41);
00279 SET(d, a, b, c, 0, 11, T42);
00280 SET(c, d, a, b, 3, 16, T43);
00281 SET(b, c, d, a, 6, 23, T44);
00282 SET(a, b, c, d, 9, 4, T45);
00283 SET(d, a, b, c, 12, 11, T46);
00284 SET(c, d, a, b, 15, 16, T47);
00285 SET(b, c, d, a, 2, 23, T48);
00286 #undef SET
00287
00288
00289
00290
00291 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
00292 #define SET(a, b, c, d, k, s, Ti)\
00293 t = a + I(b,c,d) + X[k] + Ti;\
00294 a = ROTATE_LEFT(t, s) + b
00295
00296 SET(a, b, c, d, 0, 6, T49);
00297 SET(d, a, b, c, 7, 10, T50);
00298 SET(c, d, a, b, 14, 15, T51);
00299 SET(b, c, d, a, 5, 21, T52);
00300 SET(a, b, c, d, 12, 6, T53);
00301 SET(d, a, b, c, 3, 10, T54);
00302 SET(c, d, a, b, 10, 15, T55);
00303 SET(b, c, d, a, 1, 21, T56);
00304 SET(a, b, c, d, 8, 6, T57);
00305 SET(d, a, b, c, 15, 10, T58);
00306 SET(c, d, a, b, 6, 15, T59);
00307 SET(b, c, d, a, 13, 21, T60);
00308 SET(a, b, c, d, 4, 6, T61);
00309 SET(d, a, b, c, 11, 10, T62);
00310 SET(c, d, a, b, 2, 15, T63);
00311 SET(b, c, d, a, 9, 21, T64);
00312 #undef SET
00313
00314
00315
00316
00317 pms->abcd[0] += a;
00318 pms->abcd[1] += b;
00319 pms->abcd[2] += c;
00320 pms->abcd[3] += d;
00321 }
00322
00323 void
00324 md5_init(md5_state_t *pms)
00325 {
00326 pms->count[0] = pms->count[1] = 0;
00327 pms->abcd[0] = 0x67452301;
00328 pms->abcd[1] = 0xefcdab89;
00329 pms->abcd[2] = 0x98badcfe;
00330 pms->abcd[3] = 0x10325476;
00331 }
00332
00333 void
00334 md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
00335 {
00336 const md5_byte_t *p = data;
00337 int left = nbytes;
00338 int offset = (pms->count[0] >> 3) & 63;
00339 md5_word_t nbits = (md5_word_t)(nbytes << 3);
00340
00341 if (nbytes <= 0)
00342 return;
00343
00344
00345 pms->count[1] += nbytes >> 29;
00346 pms->count[0] += nbits;
00347 if (pms->count[0] < nbits)
00348 pms->count[1]++;
00349
00350
00351 if (offset) {
00352 int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
00353
00354 memcpy(pms->buf + offset, p, copy);
00355 if (offset + copy < 64)
00356 return;
00357 p += copy;
00358 left -= copy;
00359 md5_process(pms, pms->buf);
00360 }
00361
00362
00363 for (; left >= 64; p += 64, left -= 64)
00364 md5_process(pms, p);
00365
00366
00367 if (left)
00368 memcpy(pms->buf, p, left);
00369 }
00370
00371 void
00372 md5_finish(md5_state_t *pms, md5_byte_t digest[16])
00373 {
00374 static const md5_byte_t pad[64] = {
00375 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00376 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00377 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00378 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00379 };
00380 md5_byte_t data[8];
00381 int i;
00382
00383
00384 for (i = 0; i < 8; ++i)
00385 data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
00386
00387 md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
00388
00389 md5_append(pms, data, 8);
00390 for (i = 0; i < 16; ++i)
00391 digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
00392 }