1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/tools/gamedata_md5/md5.cpp Sun Aug 17 18:27:51 2008 +0000
1.3 @@ -0,0 +1,485 @@
1.4 +// MD5.CC - source code for the C++/object oriented translation and
1.5 +// modification of MD5.
1.6 +
1.7 +// Translation and modification (c) 1995 by Mordechai T. Abzug
1.8 +
1.9 +// This translation/ modification is provided "as is," without express or
1.10 +// implied warranty of any kind.
1.11 +
1.12 +// The translator/ modifier does not claim (1) that MD5 will do what you think
1.13 +// it does; (2) that this translation/ modification is accurate; or (3) that
1.14 +// this software is "merchantible." (Language for this disclaimer partially
1.15 +// copied from the disclaimer below).
1.16 +
1.17 +/* based on:
1.18 +
1.19 + MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
1.20 + MDDRIVER.C - test driver for MD2, MD4 and MD5
1.21 +
1.22 +
1.23 + Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
1.24 +rights reserved.
1.25 +
1.26 +License to copy and use this software is granted provided that it
1.27 +is identified as the "RSA Data Security, Inc. MD5 Message-Digest
1.28 +Algorithm" in all material mentioning or referencing this software
1.29 +or this function.
1.30 +
1.31 +License is also granted to make and use derivative works provided
1.32 +that such works are identified as "derived from the RSA Data
1.33 +Security, Inc. MD5 Message-Digest Algorithm" in all material
1.34 +mentioning or referencing the derived work.
1.35 +
1.36 +RSA Data Security, Inc. makes no representations concerning either
1.37 +the merchantability of this software or the suitability of this
1.38 +software for any particular purpose. It is provided "as is"
1.39 +without express or implied warranty of any kind.
1.40 +
1.41 +These notices must be retained in any copies of any part of this
1.42 +documentation and/or software.
1.43 +
1.44 + */
1.45 +
1.46 +#include "md5.h"
1.47 +
1.48 +#include <assert.h>
1.49 +#include <string.h>
1.50 +
1.51 +// MD5 simple initialization method
1.52 +
1.53 +MD5::MD5(){
1.54 +
1.55 + init();
1.56 +
1.57 +}
1.58 +
1.59 +
1.60 +// MD5 block update operation. Continues an MD5 message-digest
1.61 +// operation, processing another message block, and updating the
1.62 +// context.
1.63 +
1.64 +void MD5::update (uint1 *input, uint4 input_length) {
1.65 +
1.66 + uint4 input_index, buffer_index;
1.67 + uint4 buffer_space; // how much space is left in buffer
1.68 +
1.69 + if (finalized){ // so we can't update!
1.70 + /*cerr << "MD5::update: Can't update a finalized digest!" << endl;*/
1.71 + return;
1.72 + }
1.73 +
1.74 + // Compute number of bytes mod 64
1.75 + buffer_index = (unsigned int)((count[0] >> 3) & 0x3F);
1.76 +
1.77 + // Update number of bits
1.78 + if ( (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) )
1.79 + count[1]++;
1.80 +
1.81 + count[1] += ((uint4)input_length >> 29);
1.82 +
1.83 +
1.84 + buffer_space = 64 - buffer_index; // how much space is left in buffer
1.85 +
1.86 + // Transform as many times as possible.
1.87 + if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
1.88 + // fill the rest of the buffer and transform
1.89 + memcpy (buffer + buffer_index, input, buffer_space);
1.90 + transform (buffer);
1.91 +
1.92 + // now, transform each 64-byte piece of the input, bypassing the buffer
1.93 + for (input_index = buffer_space; input_index + 63 < input_length;
1.94 + input_index += 64)
1.95 + transform (input+input_index);
1.96 +
1.97 + buffer_index = 0; // so we can buffer remaining
1.98 + }
1.99 + else
1.100 + input_index=0; // so we can buffer the whole input
1.101 +
1.102 +
1.103 + // and here we do the buffering:
1.104 + memcpy(buffer+buffer_index, input+input_index, input_length-input_index);
1.105 +}
1.106 +
1.107 +
1.108 +
1.109 +// MD5 update for files.
1.110 +// Like above, except that it works on files (and uses above as a primitive.)
1.111 +
1.112 +void MD5::update(FILE *file){
1.113 +
1.114 + unsigned char buffer[1024];
1.115 + int len;
1.116 +
1.117 + while ((len=fread(buffer, 1, 1024, file)))
1.118 + update(buffer, len);
1.119 +
1.120 + fclose (file);
1.121 +
1.122 +}
1.123 +
1.124 +
1.125 +// MD5 finalization. Ends an MD5 message-digest operation, writing the
1.126 +// the message digest and zeroizing the context.
1.127 +
1.128 +
1.129 +void MD5::finalize (){
1.130 +
1.131 + unsigned char bits[8];
1.132 + unsigned int index, padLen;
1.133 + static uint1 PADDING[64]={
1.134 + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1.135 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1.136 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1.137 + };
1.138 +
1.139 + if (finalized){
1.140 + /* cerr << "MD5::finalize: Already finalized this digest!" << endl;*/
1.141 + return;
1.142 + }
1.143 +
1.144 + // Save number of bits
1.145 + encode (bits, count, 8);
1.146 +
1.147 + // Pad out to 56 mod 64.
1.148 + index = (uint4) ((count[0] >> 3) & 0x3f);
1.149 + padLen = (index < 56) ? (56 - index) : (120 - index);
1.150 + update (PADDING, padLen);
1.151 +
1.152 + // Append length (before padding)
1.153 + update (bits, 8);
1.154 +
1.155 + // Store state in digest
1.156 + encode (digest, state, 16);
1.157 +
1.158 + // Zeroize sensitive information
1.159 + memset (buffer, 0, sizeof(*buffer));
1.160 +
1.161 + finalized=1;
1.162 +
1.163 +}
1.164 +
1.165 +
1.166 +
1.167 +
1.168 +MD5::MD5(FILE *file){
1.169 +
1.170 + init(); // must be called be all constructors
1.171 + update(file);
1.172 + finalize ();
1.173 +}
1.174 +
1.175 +unsigned char *MD5::raw_digest(){
1.176 +
1.177 + uint1 *s = new uint1[16];
1.178 +
1.179 + if (!finalized){
1.180 +/* cerr << "MD5::raw_digest: Can't get digest if you haven't "<<
1.181 + "finalized the digest!" <<endl;*/
1.182 + return ( (unsigned char*) "");
1.183 + }
1.184 +
1.185 + memcpy(s, digest, 16);
1.186 + return s;
1.187 +}
1.188 +
1.189 +unsigned char *MD5::raw_digest(unsigned char buffer[16])
1.190 +{
1.191 + if (!finalized)
1.192 + {
1.193 + return ( (unsigned char*) "");
1.194 + }
1.195 +
1.196 + memcpy(buffer, digest, 16);
1.197 + return buffer;
1.198 +}
1.199 +
1.200 +
1.201 +
1.202 +char *MD5::hex_digest(){
1.203 +
1.204 + int i;
1.205 + char *s= new char[33];
1.206 +
1.207 + if (!finalized){
1.208 +/* cerr << "MD5::hex_digest: Can't get digest if you haven't "<<
1.209 + "finalized the digest!" <<endl;*/
1.210 + return "";
1.211 + }
1.212 +
1.213 + for (i=0; i<16; i++)
1.214 + sprintf(s+i*2, "%02x", digest[i]);
1.215 +
1.216 + s[32]='\0';
1.217 +
1.218 + return s;
1.219 +}
1.220 +
1.221 +
1.222 +char *MD5::hex_digest(char buffer[33]){
1.223 +
1.224 + int i;
1.225 +
1.226 + if (!finalized)
1.227 + {
1.228 + /* cerr << "MD5::hex_digest: Can't get digest if you haven't "<<
1.229 + "finalized the digest!" <<endl;*/
1.230 + return "";
1.231 + }
1.232 +
1.233 + for (i=0; i<16; i++)
1.234 + sprintf(buffer+i*2, "%02x", digest[i]);
1.235 +
1.236 + buffer[32]='\0';
1.237 +
1.238 + return buffer;
1.239 +}
1.240 +
1.241 +
1.242 +// PRIVATE METHODS:
1.243 +
1.244 +
1.245 +
1.246 +void MD5::init(){
1.247 + finalized=0; // we just started!
1.248 +
1.249 + // Nothing counted, so count=0
1.250 + count[0] = 0;
1.251 + count[1] = 0;
1.252 +
1.253 + // Load magic initialization constants.
1.254 + state[0] = 0x67452301;
1.255 + state[1] = 0xefcdab89;
1.256 + state[2] = 0x98badcfe;
1.257 + state[3] = 0x10325476;
1.258 +}
1.259 +
1.260 +
1.261 +
1.262 +// Constants for MD5Transform routine.
1.263 +// Although we could use C++ style constants, defines are actually better,
1.264 +// since they let us easily evade scope clashes.
1.265 +
1.266 +#define S11 7
1.267 +#define S12 12
1.268 +#define S13 17
1.269 +#define S14 22
1.270 +#define S21 5
1.271 +#define S22 9
1.272 +#define S23 14
1.273 +#define S24 20
1.274 +#define S31 4
1.275 +#define S32 11
1.276 +#define S33 16
1.277 +#define S34 23
1.278 +#define S41 6
1.279 +#define S42 10
1.280 +#define S43 15
1.281 +#define S44 21
1.282 +
1.283 +
1.284 +
1.285 +
1.286 +// MD5 basic transformation. Transforms state based on block.
1.287 +void MD5::transform (uint1 block[64]){
1.288 +
1.289 + uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
1.290 +
1.291 + decode (x, block, 64);
1.292 +
1.293 + assert(!finalized); // not just a user error, since the method is private
1.294 +
1.295 + /* Round 1 */
1.296 + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
1.297 + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
1.298 + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
1.299 + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
1.300 + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
1.301 + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
1.302 + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
1.303 + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
1.304 + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
1.305 + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
1.306 + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
1.307 + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
1.308 + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
1.309 + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
1.310 + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
1.311 + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
1.312 +
1.313 + /* Round 2 */
1.314 + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
1.315 + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
1.316 + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
1.317 + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
1.318 + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
1.319 + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
1.320 + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
1.321 + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
1.322 + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
1.323 + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
1.324 + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
1.325 + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
1.326 + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
1.327 + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
1.328 + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
1.329 + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
1.330 +
1.331 + /* Round 3 */
1.332 + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
1.333 + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
1.334 + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
1.335 + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
1.336 + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
1.337 + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
1.338 + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
1.339 + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
1.340 + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
1.341 + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
1.342 + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
1.343 + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
1.344 + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
1.345 + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
1.346 + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
1.347 + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
1.348 +
1.349 + /* Round 4 */
1.350 + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
1.351 + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
1.352 + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
1.353 + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
1.354 + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
1.355 + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
1.356 + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
1.357 + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
1.358 + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
1.359 + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
1.360 + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
1.361 + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
1.362 + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
1.363 + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
1.364 + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
1.365 + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
1.366 +
1.367 + state[0] += a;
1.368 + state[1] += b;
1.369 + state[2] += c;
1.370 + state[3] += d;
1.371 +
1.372 + // Zeroize sensitive information.
1.373 + memset ( (uint1 *) x, 0, sizeof(x));
1.374 +
1.375 +}
1.376 +
1.377 +
1.378 +
1.379 +// Encodes input (UINT4) into output (unsigned char). Assumes len is
1.380 +// a multiple of 4.
1.381 +void MD5::encode (uint1 *output, uint4 *input, uint4 len) {
1.382 +
1.383 + unsigned int i, j;
1.384 +
1.385 + for (i = 0, j = 0; j < len; i++, j += 4) {
1.386 + output[j] = (uint1) (input[i] & 0xff);
1.387 + output[j+1] = (uint1) ((input[i] >> 8) & 0xff);
1.388 + output[j+2] = (uint1) ((input[i] >> 16) & 0xff);
1.389 + output[j+3] = (uint1) ((input[i] >> 24) & 0xff);
1.390 + }
1.391 +}
1.392 +
1.393 +
1.394 +
1.395 +
1.396 +// Decodes input (unsigned char) into output (UINT4). Assumes len is
1.397 +// a multiple of 4.
1.398 +void MD5::decode (uint4 *output, uint1 *input, uint4 len){
1.399 +
1.400 + unsigned int i, j;
1.401 +
1.402 + for (i = 0, j = 0; j < len; i++, j += 4)
1.403 + output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
1.404 + (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
1.405 +}
1.406 +
1.407 +
1.408 +
1.409 +
1.410 +
1.411 +// Note: Replace "for loop" with standard memcpy if possible.
1.412 +void MD5::memcpy (uint1 *output, uint1 *input, uint4 len){
1.413 +
1.414 + unsigned int i;
1.415 +
1.416 + for (i = 0; i < len; i++)
1.417 + output[i] = input[i];
1.418 +}
1.419 +
1.420 +
1.421 +
1.422 +// Note: Replace "for loop" with standard memset if possible.
1.423 +void MD5::memset (uint1 *output, uint1 value, uint4 len){
1.424 +
1.425 + unsigned int i;
1.426 +
1.427 + for (i = 0; i < len; i++)
1.428 + output[i] = value;
1.429 +}
1.430 +
1.431 +
1.432 +
1.433 +// ROTATE_LEFT rotates x left n bits.
1.434 +
1.435 +inline unsigned int MD5::rotate_left (uint4 x, uint4 n){
1.436 + return (x << n) | (x >> (32-n)) ;
1.437 +}
1.438 +
1.439 +
1.440 +
1.441 +
1.442 +// F, G, H and I are basic MD5 functions.
1.443 +
1.444 +inline unsigned int MD5::F (uint4 x, uint4 y, uint4 z){
1.445 + return (x & y) | (~x & z);
1.446 +}
1.447 +
1.448 +inline unsigned int MD5::G (uint4 x, uint4 y, uint4 z){
1.449 + return (x & z) | (y & ~z);
1.450 +}
1.451 +
1.452 +inline unsigned int MD5::H (uint4 x, uint4 y, uint4 z){
1.453 + return x ^ y ^ z;
1.454 +}
1.455 +
1.456 +inline unsigned int MD5::I (uint4 x, uint4 y, uint4 z){
1.457 + return y ^ (x | ~z);
1.458 +}
1.459 +
1.460 +
1.461 +
1.462 +// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
1.463 +// Rotation is separate from addition to prevent recomputation.
1.464 +
1.465 +
1.466 +inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
1.467 + uint4 s, uint4 ac){
1.468 + a += F(b, c, d) + x + ac;
1.469 + a = rotate_left (a, s) +b;
1.470 +}
1.471 +
1.472 +inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
1.473 + uint4 s, uint4 ac){
1.474 + a += G(b, c, d) + x + ac;
1.475 + a = rotate_left (a, s) +b;
1.476 +}
1.477 +
1.478 +inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
1.479 + uint4 s, uint4 ac){
1.480 + a += H(b, c, d) + x + ac;
1.481 + a = rotate_left (a, s) +b;
1.482 +}
1.483 +
1.484 +inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
1.485 + uint4 s, uint4 ac){
1.486 + a += I(b, c, d) + x + ac;
1.487 + a = rotate_left (a, s) +b;
1.488 +}