pred@2142: // MD5.CC - source code for the C++/object oriented translation and pred@2142: // modification of MD5. pred@2142: pred@2142: // Translation and modification (c) 1995 by Mordechai T. Abzug pred@2142: pred@2142: // This translation/ modification is provided "as is," without express or pred@2142: // implied warranty of any kind. pred@2142: pred@2142: // The translator/ modifier does not claim (1) that MD5 will do what you think pred@2142: // it does; (2) that this translation/ modification is accurate; or (3) that pred@2142: // this software is "merchantible." (Language for this disclaimer partially pred@2142: // copied from the disclaimer below). pred@2142: pred@2142: /* based on: pred@2142: pred@2142: MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm pred@2142: MDDRIVER.C - test driver for MD2, MD4 and MD5 pred@2142: pred@2142: pred@2142: Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All pred@2142: rights reserved. pred@2142: pred@2142: License to copy and use this software is granted provided that it pred@2142: is identified as the "RSA Data Security, Inc. MD5 Message-Digest pred@2142: Algorithm" in all material mentioning or referencing this software pred@2142: or this function. pred@2142: pred@2142: License is also granted to make and use derivative works provided pred@2142: that such works are identified as "derived from the RSA Data pred@2142: Security, Inc. MD5 Message-Digest Algorithm" in all material pred@2142: mentioning or referencing the derived work. pred@2142: pred@2142: RSA Data Security, Inc. makes no representations concerning either pred@2142: the merchantability of this software or the suitability of this pred@2142: software for any particular purpose. It is provided "as is" pred@2142: without express or implied warranty of any kind. pred@2142: pred@2142: These notices must be retained in any copies of any part of this pred@2142: documentation and/or software. pred@2142: pred@2142: */ pred@2142: pred@2142: #include "md5.h" pred@2142: pred@2142: #include pred@2142: #include pred@2142: pred@2142: // MD5 simple initialization method pred@2142: pred@2142: MD5::MD5(){ pred@2142: pred@2142: init(); pred@2142: pred@2142: } pred@2142: pred@2142: pred@2142: // MD5 block update operation. Continues an MD5 message-digest pred@2142: // operation, processing another message block, and updating the pred@2142: // context. pred@2142: pred@2142: void MD5::update (uint1 *input, uint4 input_length) { pred@2142: pred@2142: uint4 input_index, buffer_index; pred@2142: uint4 buffer_space; // how much space is left in buffer pred@2142: pred@2142: if (finalized){ // so we can't update! pred@2142: /*cerr << "MD5::update: Can't update a finalized digest!" << endl;*/ pred@2142: return; pred@2142: } pred@2142: pred@2142: // Compute number of bytes mod 64 pred@2142: buffer_index = (unsigned int)((count[0] >> 3) & 0x3F); pred@2142: pred@2142: // Update number of bits pred@2142: if ( (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) ) pred@2142: count[1]++; pred@2142: pred@2142: count[1] += ((uint4)input_length >> 29); pred@2142: pred@2142: pred@2142: buffer_space = 64 - buffer_index; // how much space is left in buffer pred@2142: pred@2142: // Transform as many times as possible. pred@2142: if (input_length >= buffer_space) { // ie. we have enough to fill the buffer pred@2142: // fill the rest of the buffer and transform pred@2142: memcpy (buffer + buffer_index, input, buffer_space); pred@2142: transform (buffer); pred@2142: pred@2142: // now, transform each 64-byte piece of the input, bypassing the buffer pred@2142: for (input_index = buffer_space; input_index + 63 < input_length; pred@2142: input_index += 64) pred@2142: transform (input+input_index); pred@2142: pred@2142: buffer_index = 0; // so we can buffer remaining pred@2142: } pred@2142: else pred@2142: input_index=0; // so we can buffer the whole input pred@2142: pred@2142: pred@2142: // and here we do the buffering: pred@2142: memcpy(buffer+buffer_index, input+input_index, input_length-input_index); pred@2142: } pred@2142: pred@2142: pred@2142: pred@2142: // MD5 update for files. pred@2142: // Like above, except that it works on files (and uses above as a primitive.) pred@2142: pred@2142: void MD5::update(FILE *file){ pred@2142: pred@2142: unsigned char buffer[1024]; pred@2142: int len; pred@2142: pred@2142: while ((len=fread(buffer, 1, 1024, file))) pred@2142: update(buffer, len); pred@2142: pred@2142: fclose (file); pred@2142: pred@2142: } pred@2142: pred@2142: pred@2142: // MD5 finalization. Ends an MD5 message-digest operation, writing the pred@2142: // the message digest and zeroizing the context. pred@2142: pred@2142: pred@2142: void MD5::finalize (){ pred@2142: pred@2142: unsigned char bits[8]; pred@2142: unsigned int index, padLen; pred@2142: static uint1 PADDING[64]={ pred@2142: 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pred@2142: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pred@2142: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 pred@2142: }; pred@2142: pred@2142: if (finalized){ pred@2142: /* cerr << "MD5::finalize: Already finalized this digest!" << endl;*/ pred@2142: return; pred@2142: } pred@2142: pred@2142: // Save number of bits pred@2142: encode (bits, count, 8); pred@2142: pred@2142: // Pad out to 56 mod 64. pred@2142: index = (uint4) ((count[0] >> 3) & 0x3f); pred@2142: padLen = (index < 56) ? (56 - index) : (120 - index); pred@2142: update (PADDING, padLen); pred@2142: pred@2142: // Append length (before padding) pred@2142: update (bits, 8); pred@2142: pred@2142: // Store state in digest pred@2142: encode (digest, state, 16); pred@2142: pred@2142: // Zeroize sensitive information pred@2142: memset (buffer, 0, sizeof(*buffer)); pred@2142: pred@2142: finalized=1; pred@2142: pred@2142: } pred@2142: pred@2142: pred@2142: pred@2142: pred@2142: MD5::MD5(FILE *file){ pred@2142: pred@2142: init(); // must be called be all constructors pred@2142: update(file); pred@2142: finalize (); pred@2142: } pred@2142: pred@2142: unsigned char *MD5::raw_digest(){ pred@2142: pred@2142: uint1 *s = new uint1[16]; pred@2142: pred@2142: if (!finalized){ pred@2142: /* cerr << "MD5::raw_digest: Can't get digest if you haven't "<< pred@2142: "finalized the digest!" <> 8) & 0xff); pred@2142: output[j+2] = (uint1) ((input[i] >> 16) & 0xff); pred@2142: output[j+3] = (uint1) ((input[i] >> 24) & 0xff); pred@2142: } pred@2142: } pred@2142: pred@2142: pred@2142: pred@2142: pred@2142: // Decodes input (unsigned char) into output (UINT4). Assumes len is pred@2142: // a multiple of 4. pred@2142: void MD5::decode (uint4 *output, uint1 *input, uint4 len){ pred@2142: pred@2142: unsigned int i, j; pred@2142: pred@2142: for (i = 0, j = 0; j < len; i++, j += 4) pred@2142: output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) | pred@2142: (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24); pred@2142: } pred@2142: pred@2142: pred@2142: pred@2142: pred@2142: pred@2142: // Note: Replace "for loop" with standard memcpy if possible. pred@2142: void MD5::memcpy (uint1 *output, uint1 *input, uint4 len){ pred@2142: pred@2142: unsigned int i; pred@2142: pred@2142: for (i = 0; i < len; i++) pred@2142: output[i] = input[i]; pred@2142: } pred@2142: pred@2142: pred@2142: pred@2142: // Note: Replace "for loop" with standard memset if possible. pred@2142: void MD5::memset (uint1 *output, uint1 value, uint4 len){ pred@2142: pred@2142: unsigned int i; pred@2142: pred@2142: for (i = 0; i < len; i++) pred@2142: output[i] = value; pred@2142: } pred@2142: pred@2142: pred@2142: pred@2142: // ROTATE_LEFT rotates x left n bits. pred@2142: pred@2142: inline unsigned int MD5::rotate_left (uint4 x, uint4 n){ pred@2142: return (x << n) | (x >> (32-n)) ; pred@2142: } pred@2142: pred@2142: pred@2142: pred@2142: pred@2142: // F, G, H and I are basic MD5 functions. pred@2142: pred@2142: inline unsigned int MD5::F (uint4 x, uint4 y, uint4 z){ pred@2142: return (x & y) | (~x & z); pred@2142: } pred@2142: pred@2142: inline unsigned int MD5::G (uint4 x, uint4 y, uint4 z){ pred@2142: return (x & z) | (y & ~z); pred@2142: } pred@2142: pred@2142: inline unsigned int MD5::H (uint4 x, uint4 y, uint4 z){ pred@2142: return x ^ y ^ z; pred@2142: } pred@2142: pred@2142: inline unsigned int MD5::I (uint4 x, uint4 y, uint4 z){ pred@2142: return y ^ (x | ~z); pred@2142: } pred@2142: pred@2142: pred@2142: pred@2142: // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. pred@2142: // Rotation is separate from addition to prevent recomputation. pred@2142: pred@2142: pred@2142: inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, pred@2142: uint4 s, uint4 ac){ pred@2142: a += F(b, c, d) + x + ac; pred@2142: a = rotate_left (a, s) +b; pred@2142: } pred@2142: pred@2142: inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, pred@2142: uint4 s, uint4 ac){ pred@2142: a += G(b, c, d) + x + ac; pred@2142: a = rotate_left (a, s) +b; pred@2142: } pred@2142: pred@2142: inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, pred@2142: uint4 s, uint4 ac){ pred@2142: a += H(b, c, d) + x + ac; pred@2142: a = rotate_left (a, s) +b; pred@2142: } pred@2142: pred@2142: inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, pred@2142: uint4 s, uint4 ac){ pred@2142: a += I(b, c, d) + x + ac; pred@2142: a = rotate_left (a, s) +b; pred@2142: }