src/network/md5.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 *************************************************************************
00004 
00005 ArmageTron -- Just another Tron Lightcycle Game in 3D.
00006 
00007 This file was taken from GNU-Ghostscript from Aladdin Enterprises; original
00008 header and copyright notice follow. As I interpret the copyright and licensing
00009 statement, it would be OK to keep this code even for non-GPL distribution.
00010 ( may be needed sometime if third party, non-Free code gets integrated )
00011 
00012 Changes made: included memory.h and string.h for windows compatibility
00013 
00014 **************************************************************************
00015 
00016 This program is free software; you can redistribute it and/or
00017 modify it under the terms of the GNU General Public License
00018 as published by the Free Software Foundation; either version 2
00019 of the License, or (at your option) any later version.
00020 
00021 This program is distributed in the hope that it will be useful,
00022 but WITHOUT ANY WARRANTY; without even the implied warranty of
00023 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024 GNU General Public License for more details.
00025 
00026 You should have received a copy of the GNU General Public License
00027 along with this program; if not, write to the Free Software
00028 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00029   
00030 ***************************************************************************
00031 
00032 */
00033 
00034 /*
00035   Copyright (C) 1999, 2000 Aladdin Enterprises.  All rights reserved.
00036 
00037   This software is provided 'as-is', without any express or implied
00038   warranty.  In no event will the authors be held liable for any damages
00039   arising from the use of this software.
00040 
00041   Permission is granted to anyone to use this software for any purpose,
00042   including commercial applications, and to alter it and redistribute it
00043   freely, subject to the following restrictions:
00044 
00045   1. The origin of this software must not be misrepresented; you must not
00046      claim that you wrote the original software. If you use this software
00047      in a product, an acknowledgment in the product documentation would be
00048      appreciated but is not required.
00049   2. Altered source versions must be plainly marked as such, and must not be
00050      misrepresented as being the original software.
00051   3. This notice may not be removed or altered from any source distribution.
00052 
00053   L. Peter Deutsch
00054   ghost@aladdin.com
00055 
00056  */
00057 /*$RCSfile$ $Revision: 7538 $ */
00058 /*
00059   Independent implementation of MD5 (RFC 1321).
00060 
00061   This code implements the MD5 Algorithm defined in RFC 1321.
00062   It is derived directly from the text of the RFC and not from the
00063   reference implementation.
00064 
00065   The original and principal author of md5.c is L. Peter Deutsch
00066   <ghost@aladdin.com>.  Other authors are noted in the change history
00067   that follows (in reverse chronological order):
00068 
00069   2000-07-03 lpd Patched to eliminate warnings about "constant is
00070                 unsigned in ANSI C, signed in traditional";
00071                 made test program self-checking.
00072   1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
00073   1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
00074   1999-05-03 lpd Original version.
00075  */
00076 
00077 #include "md5.h"
00078 
00079 #include <string>
00080 #include <memory>
00081 #include <string.h>
00082 
00083 #ifdef TEST
00084 /*
00085  * Compile with -DTEST to create a self-contained executable test program.
00086  * The test program should print out the same values as given in section
00087  * A.5 of RFC 1321, reproduced below.
00088  */
00089 
00090 main()
00091 {
00092     static const char *const test[7*2] = {
00093                                              "", "d41d8cd98f00b204e9800998ecf8427e",
00094                                              "a", "0cc175b9c0f1b6a831c399e269772661",
00095                                              "abc", "900150983cd24fb0d6963f7d28e17f72",
00096                                              "message digest", "f96b697d7cb7938d525a2f31aaf161d0",
00097                                              "abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b",
00098                                              "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
00099                                              "d174ab98d277d9f5a5611c2c9f419d9f",
00100                                              "12345678901234567890123456789012345678901234567890123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a"
00101                                          };
00102     int i;
00103 
00104     for (i = 0; i < 7*2; i += 2) {
00105         md5_state_t state;
00106         md5_byte_t digest[16];
00107         char hex_output[16*2 + 1];
00108         int di;
00109 
00110         md5_init(&state);
00111         md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i]));
00112         md5_finish(&state, digest);
00113         printf("MD5 (\"%s\") = ", test[i]);
00114         for (di = 0; di < 16; ++di)
00115             sprintf(hex_output + di * 2, "%02x", digest[di]);
00116         puts(hex_output);
00117         if (strcmp(hex_output, test[i + 1]))
00118             printf("**** ERROR, should be: %s\n", test[i + 1]);
00119     }
00120     return 0;
00121 }
00122 #endif /* TEST */
00123 
00124 
00125 /*
00126  * For reference, here is the program that computed the T values.
00127  */
00128 #ifdef COMPUTE_T_VALUES
00129 #include <math>
00130 main()
00131 {
00132     int i;
00133     for (i = 1; i <= 64; ++i) {
00134         unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i)));
00135 
00136         /*
00137          * The following nonsense is only to avoid compiler warnings about
00138          * "integer constant is unsigned in ANSI C, signed with -traditional".
00139          */
00140         if (v >> 31) {
00141             printf("#define T%d /* 0x%08lx */ (T_MASK ^ 0x%08lx)\n", i,
00142                    v, (unsigned long)(unsigned int)(~v));
00143         } else {
00144             printf("#define T%d    0x%08lx\n", i, v);
00145         }
00146     }
00147     return 0;
00148 }
00149 #endif /* COMPUTE_T_VALUES */
00150 /*
00151  * End of T computation program.
00152  */
00153 #define T_MASK ((md5_word_t)~0)
00154 #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
00155 #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
00156 #define T3    0x242070db
00157 #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
00158 #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
00159 #define T6    0x4787c62a
00160 #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
00161 #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
00162 #define T9    0x698098d8
00163 #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
00164 #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
00165 #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
00166 #define T13    0x6b901122
00167 #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
00168 #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
00169 #define T16    0x49b40821
00170 #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
00171 #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
00172 #define T19    0x265e5a51
00173 #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
00174 #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
00175 #define T22    0x02441453
00176 #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
00177 #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
00178 #define T25    0x21e1cde6
00179 #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
00180 #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
00181 #define T28    0x455a14ed
00182 #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
00183 #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
00184 #define T31    0x676f02d9
00185 #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
00186 #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
00187 #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
00188 #define T35    0x6d9d6122
00189 #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
00190 #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
00191 #define T38    0x4bdecfa9
00192 #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
00193 #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
00194 #define T41    0x289b7ec6
00195 #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
00196 #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
00197 #define T44    0x04881d05
00198 #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
00199 #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
00200 #define T47    0x1fa27cf8
00201 #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
00202 #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
00203 #define T50    0x432aff97
00204 #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
00205 #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
00206 #define T53    0x655b59c3
00207 #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
00208 #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
00209 #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
00210 #define T57    0x6fa87e4f
00211 #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
00212 #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
00213 #define T60    0x4e0811a1
00214 #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
00215 #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
00216 #define T63    0x2ad7d2bb
00217 #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
00218 
00219 
00220 static void
00221 md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
00222 {
00223     md5_word_t
00224     a = pms->abcd[0], b = pms->abcd[1],
00225                           c = pms->abcd[2], d = pms->abcd[3];
00226     md5_word_t t;
00227 
00228 #ifndef ARCH_IS_BIG_ENDIAN
00229 # define ARCH_IS_BIG_ENDIAN 1   /* slower, default implementation */
00230 #endif
00231 #if ARCH_IS_BIG_ENDIAN
00232 
00233     /*
00234      * On big-endian machines, we must arrange the bytes in the right
00235      * order.  (This also works on machines of unknown byte order.)
00236      */
00237     md5_word_t X[16];
00238     const md5_byte_t *xp = data;
00239     int i;
00240 
00241     for (i = 0; i < 16; ++i, xp += 4)
00242         X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
00243 
00244 #else  /* !ARCH_IS_BIG_ENDIAN */
00245 
00246     /*
00247     * On little-endian machines, we can process properly aligned data
00248     * without copying it.
00249     */
00250     md5_word_t xbuf[16];
00251     const md5_word_t *X;
00252 
00253     if (!((data - (const md5_byte_t *)0) & 3)) {
00254         /* data are properly aligned */
00255         X = (const md5_word_t *)data;
00256     } else {
00257         /* not aligned */
00258         memcpy(xbuf, data, 64);
00259         X = xbuf;
00260     }
00261 #endif
00262 
00263 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
00264 
00265     /* Round 1. */
00266     /* Let [abcd k s i] denote the operation
00267        a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
00268 #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
00269 #define SET(a, b, c, d, k, s, Ti)\
00270   t = a + F(b,c,d) + X[k] + Ti;\
00271   a = ROTATE_LEFT(t, s) + b
00272     /* Do the following 16 operations. */
00273     SET(a, b, c, d,  0,  7,  T1);
00274     SET(d, a, b, c,  1, 12,  T2);
00275     SET(c, d, a, b,  2, 17,  T3);
00276     SET(b, c, d, a,  3, 22,  T4);
00277     SET(a, b, c, d,  4,  7,  T5);
00278     SET(d, a, b, c,  5, 12,  T6);
00279     SET(c, d, a, b,  6, 17,  T7);
00280     SET(b, c, d, a,  7, 22,  T8);
00281     SET(a, b, c, d,  8,  7,  T9);
00282     SET(d, a, b, c,  9, 12, T10);
00283     SET(c, d, a, b, 10, 17, T11);
00284     SET(b, c, d, a, 11, 22, T12);
00285     SET(a, b, c, d, 12,  7, T13);
00286     SET(d, a, b, c, 13, 12, T14);
00287     SET(c, d, a, b, 14, 17, T15);
00288     SET(b, c, d, a, 15, 22, T16);
00289 #undef SET
00290 
00291     /* Round 2. */
00292     /* Let [abcd k s i] denote the operation
00293          a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
00294 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
00295 #define SET(a, b, c, d, k, s, Ti)\
00296   t = a + G(b,c,d) + X[k] + Ti;\
00297   a = ROTATE_LEFT(t, s) + b
00298     /* Do the following 16 operations. */
00299     SET(a, b, c, d,  1,  5, T17);
00300     SET(d, a, b, c,  6,  9, T18);
00301     SET(c, d, a, b, 11, 14, T19);
00302     SET(b, c, d, a,  0, 20, T20);
00303     SET(a, b, c, d,  5,  5, T21);
00304     SET(d, a, b, c, 10,  9, T22);
00305     SET(c, d, a, b, 15, 14, T23);
00306     SET(b, c, d, a,  4, 20, T24);
00307     SET(a, b, c, d,  9,  5, T25);
00308     SET(d, a, b, c, 14,  9, T26);
00309     SET(c, d, a, b,  3, 14, T27);
00310     SET(b, c, d, a,  8, 20, T28);
00311     SET(a, b, c, d, 13,  5, T29);
00312     SET(d, a, b, c,  2,  9, T30);
00313     SET(c, d, a, b,  7, 14, T31);
00314     SET(b, c, d, a, 12, 20, T32);
00315 #undef SET
00316 
00317     /* Round 3. */
00318     /* Let [abcd k s t] denote the operation
00319          a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
00320 #define H(x, y, z) ((x) ^ (y) ^ (z))
00321 #define SET(a, b, c, d, k, s, Ti)\
00322   t = a + H(b,c,d) + X[k] + Ti;\
00323   a = ROTATE_LEFT(t, s) + b
00324     /* Do the following 16 operations. */
00325     SET(a, b, c, d,  5,  4, T33);
00326     SET(d, a, b, c,  8, 11, T34);
00327     SET(c, d, a, b, 11, 16, T35);
00328     SET(b, c, d, a, 14, 23, T36);
00329     SET(a, b, c, d,  1,  4, T37);
00330     SET(d, a, b, c,  4, 11, T38);
00331     SET(c, d, a, b,  7, 16, T39);
00332     SET(b, c, d, a, 10, 23, T40);
00333     SET(a, b, c, d, 13,  4, T41);
00334     SET(d, a, b, c,  0, 11, T42);
00335     SET(c, d, a, b,  3, 16, T43);
00336     SET(b, c, d, a,  6, 23, T44);
00337     SET(a, b, c, d,  9,  4, T45);
00338     SET(d, a, b, c, 12, 11, T46);
00339     SET(c, d, a, b, 15, 16, T47);
00340     SET(b, c, d, a,  2, 23, T48);
00341 #undef SET
00342 
00343     /* Round 4. */
00344     /* Let [abcd k s t] denote the operation
00345          a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
00346 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
00347 #define SET(a, b, c, d, k, s, Ti)\
00348   t = a + I(b,c,d) + X[k] + Ti;\
00349   a = ROTATE_LEFT(t, s) + b
00350     /* Do the following 16 operations. */
00351     SET(a, b, c, d,  0,  6, T49);
00352     SET(d, a, b, c,  7, 10, T50);
00353     SET(c, d, a, b, 14, 15, T51);
00354     SET(b, c, d, a,  5, 21, T52);
00355     SET(a, b, c, d, 12,  6, T53);
00356     SET(d, a, b, c,  3, 10, T54);
00357     SET(c, d, a, b, 10, 15, T55);
00358     SET(b, c, d, a,  1, 21, T56);
00359     SET(a, b, c, d,  8,  6, T57);
00360     SET(d, a, b, c, 15, 10, T58);
00361     SET(c, d, a, b,  6, 15, T59);
00362     SET(b, c, d, a, 13, 21, T60);
00363     SET(a, b, c, d,  4,  6, T61);
00364     SET(d, a, b, c, 11, 10, T62);
00365     SET(c, d, a, b,  2, 15, T63);
00366     SET(b, c, d, a,  9, 21, T64);
00367 #undef SET
00368 
00369     /* Then perform the following additions. (That is increment each
00370        of the four registers by the value it had before this block
00371        was started.) */
00372     pms->abcd[0] += a;
00373     pms->abcd[1] += b;
00374     pms->abcd[2] += c;
00375     pms->abcd[3] += d;
00376 }
00377 
00378 void
00379 md5_init(md5_state_t *pms)
00380 {
00381     pms->count[0] = pms->count[1] = 0;
00382     pms->abcd[0] = 0x67452301;
00383     pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
00384     pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
00385     pms->abcd[3] = 0x10325476;
00386 }
00387 
00388 void
00389 md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
00390 {
00391     const md5_byte_t *p = data;
00392     int left = nbytes;
00393     int offset = (pms->count[0] >> 3) & 63;
00394     md5_word_t nbits = (md5_word_t)(nbytes << 3);
00395 
00396     if (nbytes <= 0)
00397         return;
00398 
00399     /* Update the message length. */
00400     pms->count[1] += nbytes >> 29;
00401     pms->count[0] += nbits;
00402     if (pms->count[0] < nbits)
00403         pms->count[1]++;
00404 
00405     /* Process an initial partial block. */
00406     if (offset) {
00407         int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
00408 
00409         memcpy(pms->buf + offset, p, copy);
00410         if (offset + copy < 64)
00411             return;
00412         p += copy;
00413         left -= copy;
00414         md5_process(pms, pms->buf);
00415     }
00416 
00417     /* Process full blocks. */
00418     for (; left >= 64; p += 64, left -= 64)
00419         md5_process(pms, p);
00420 
00421     /* Process a final partial block. */
00422     if (left)
00423         memcpy(pms->buf, p, left);
00424 }
00425 
00426 void
00427 md5_finish(md5_state_t *pms, md5_byte_t digest[16])
00428 {
00429     static const md5_byte_t pad[64] = {
00430                                           0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00431                                           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00432                                           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00433                                           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00434                                       };
00435     md5_byte_t data[8];
00436     int i;
00437 
00438     /* Save the length before padding. */
00439     for (i = 0; i < 8; ++i)
00440         data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
00441     /* Pad to 56 bytes mod 64. */
00442     md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
00443     /* Append the length. */
00444     md5_append(pms, data, 8);
00445     for (i = 0; i < 16; ++i)
00446         digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
00447 }

Generated on Sat Mar 15 22:55:49 2008 for Armagetron Advanced by  doxygen 1.5.4