#include "md5.h" #include #include #include // // // This MD5 module has taken from RSA group homepage.. // All of copryright and responsbility are belong to SRA. not me ! :) // Sean Kim ( kwkim@netpia.com ) // // MD5::MD5(){ init(); } void MD5::update (unsigned char *input, uint4 input_length) { uint4 input_index, buffer_index; uint4 buffer_space; // how much space is left in buffer if (finalized){ // so we can't update! cerr << "MD5::update: Can't update a finalized digest!" << endl; return; } // Compute number of bytes mod 64 buffer_index = (unsigned int)((count[0] >> 3) & 0x3F); // Update number of bits if ( (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) ) count[1]++; count[1] += ((uint4)input_length >> 29); buffer_space = 64 - buffer_index; // how much space is left in buffer // Transform as many times as possible. if (input_length >= buffer_space) { // ie. we have enough to fill the buffer // fill the rest of the buffer and transform memcpy (buffer + buffer_index, input, buffer_space); transform (buffer); // now, transform each 64-byte piece of the input, bypassing the buffer for (input_index = buffer_space; input_index + 63 < input_length; input_index += 64) transform (input+input_index); buffer_index = 0; // so we can buffer remaining } else input_index=0; // so we can buffer the whole input // and here we do the buffering: memcpy(buffer+buffer_index, input+input_index, input_length-input_index); } // MD5 update for files. // Like above, except that it works on files (and uses above as a primitive.) void MD5::update(FILE *file){ char szbuffer[1024]; int len = 0; while ((len=fread(szbuffer, 1, 1024, file))) { update((unsigned char *)szbuffer, len); } fclose (file); } // MD5 update for istreams. // Like update for files; see above. void MD5::update(istream& stream){ char szbuffer[1024]; int len; while (stream.good()){ stream.read(szbuffer, 1024); // note that return value of read is unusable. len=stream.gcount(); update((unsigned char *)szbuffer, len); } } // MD5 update for ifstreams. // Like update for files; see above. void MD5::update(ifstream& stream){ char szbuffer[1024]; int len; while (stream.good()){ stream.read(szbuffer, 1024); // note that return value of read is unusable. len=stream.gcount(); update((unsigned char *)szbuffer, len); } } // MD5 finalization. Ends an MD5 message-digest operation, writing the // the message digest and zeroizing the context. void MD5::finalize (){ unsigned char bits[8]; unsigned int index, padLen; static uint1 PADDING[64]={ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; if (finalized){ cerr << "MD5::finalize: Already finalized this digest!" << endl; return; } // Save number of bits encode (bits, count, 8); // Pad out to 56 mod 64. index = (uint4) ((count[0] >> 3) & 0x3f); padLen = (index < 56) ? (56 - index) : (120 - index); update (PADDING, padLen); // Append length (before padding) update (bits, 8); // Store state in digest encode (digest, state, 16); // Zeroize sensitive information memset (buffer, 0, sizeof(*buffer)); finalized=1; } MD5::MD5(FILE *file){ init(); // must be called be all constructors update(file); finalize (); } MD5::MD5(istream& stream){ init(); // must called by all constructors update (stream); finalize(); } MD5::MD5(ifstream& stream){ init(); // must called by all constructors update (stream); finalize(); } unsigned char *MD5::raw_digest(){ uint1 *s = new uint1[16]; if (!finalized){ cerr << "MD5::raw_digest: Can't get digest if you haven't "<< "finalized the digest!" <> 8) & 0xff); output[j+2] = (uint1) ((input[i] >> 16) & 0xff); output[j+3] = (uint1) ((input[i] >> 24) & 0xff); } } void MD5::decode (uint4 *output, uint1 *input, uint4 len){ unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) | (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24); } void MD5::memcpy (uint1 *output, uint1 *input, uint4 len){ unsigned int i; for (i = 0; i < len; i++) output[i] = input[i]; } void MD5::memset (uint1 *output, uint1 value, uint4 len){ unsigned int i; for (i = 0; i < len; i++) output[i] = value; } inline unsigned int MD5::rotate_left (uint4 x, uint4 n){ return (x << n) | (x >> (32-n)) ; } inline unsigned int MD5::F (uint4 x, uint4 y, uint4 z){ return (x & y) | (~x & z); } inline unsigned int MD5::G (uint4 x, uint4 y, uint4 z){ return (x & z) | (y & ~z); } inline unsigned int MD5::H (uint4 x, uint4 y, uint4 z){ return x ^ y ^ z; } inline unsigned int MD5::I (uint4 x, uint4 y, uint4 z){ return y ^ (x | ~z); } inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac){ a += F(b, c, d) + x + ac; a = rotate_left (a, s) +b; } inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac){ a += G(b, c, d) + x + ac; a = rotate_left (a, s) +b; } inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac){ a += H(b, c, d) + x + ac; a = rotate_left (a, s) +b; } inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac){ a += I(b, c, d) + x + ac; a = rotate_left (a, s) +b; }