CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/CondCore/ORA/src/GenMD5.cc

Go to the documentation of this file.
00001 // MD5.CC - source code for the C++/object oriented translation and 
00002 //          modification of MD5.
00003 
00004 // Translation and modification (c) 1995 by Mordechai T. Abzug 
00005 
00006 // This translation/ modification is provided "as is," without express or 
00007 // implied warranty of any kind.
00008 
00009 // The translator/ modifier does not claim (1) that MD5 will do what you think 
00010 // it does; (2) that this translation/ modification is accurate; or (3) that 
00011 // this software is "merchantible."  (Language for this disclaimer partially 
00012 // copied from the disclaimer below).
00013 
00014 /* based on:
00015 
00016    MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
00017    MDDRIVER.C - test driver for MD2, MD4 and MD5
00018 
00019 
00020    Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
00021 rights reserved.
00022 
00023 License to copy and use this software is granted provided that it
00024 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
00025 Algorithm" in all material mentioning or referencing this software
00026 or this function.
00027 
00028 License is also granted to make and use derivative works provided
00029 that such works are identified as "derived from the RSA Data
00030 Security, Inc. MD5 Message-Digest Algorithm" in all material
00031 mentioning or referencing the derived work.
00032 
00033 RSA Data Security, Inc. makes no representations concerning either
00034 the merchantability of this software or the suitability of this
00035 software for any particular purpose. It is provided "as is"
00036 without express or implied warranty of any kind.
00037 
00038 These notices must be retained in any copies of any part of this
00039 documentation and/or software.
00040 
00041 */
00042 #include <cassert>
00043 #include <string>
00044 #include <cstdio>
00045 #include <cstring>
00046 #include <iostream>
00047 
00048 using namespace std;
00049 
00050 // Constants for MD5Transform routine.
00051 // Although we could use C++ style constants, defines are actually better,
00052 // since they let us easily evade scope clashes.
00053 #define S11 7
00054 #define S12 12
00055 #define S13 17
00056 #define S14 22
00057 #define S21 5
00058 #define S22 9
00059 #define S23 14
00060 #define S24 20
00061 #define S31 4
00062 #define S32 11
00063 #define S33 16
00064 #define S34 23
00065 #define S41 6
00066 #define S42 10
00067 #define S43 15
00068 #define S44 21
00069 
00070 namespace {
00071   class MD5 {
00072   public:
00074     MD5              (unsigned char* buffer, unsigned long len);
00076     MD5              ();  
00078     void  update     (unsigned char *input, unsigned int input_length);
00079     // Finalize MD5 check-sum
00080     void  finalize   ();
00081 
00083 
00084     void raw_digest (unsigned char *buff);
00085 
00087     string       hex_digest ();
00089 
00090   private:
00091     // next, the private data:
00092     unsigned int state[4];
00093     unsigned int count[2];     // number of *bits*, mod 2^64
00094     unsigned char buffer[64];   // input buffer
00095     unsigned char digest[16];
00096     unsigned char finalized;
00097 
00098     // last, the private methods, mostly static:
00099     void init             ();               // called by all constructors
00100     void transform        (unsigned char *buffer);  // does the real update work.  Note 
00101                                             // that length is implied to be 64.
00102 
00103     static void encode    (unsigned char *dest, unsigned int *src, unsigned int length);
00104     static void decode    (unsigned int *dest, unsigned char *src, unsigned int length);
00105 
00106     // ROTATE_LEFT rotates x left n bits.
00107     static inline unsigned int  rotate_left (unsigned int x, unsigned int n)
00108     {  return (x << n) | (x >> (32-n));                             }
00109     // F, G, H and I are basic MD5 functions.
00110     static inline unsigned int  F(unsigned int x, unsigned int y, unsigned int z)
00111     {  return (x & y) | (~x & z);                                   }
00112     static inline unsigned int  G(unsigned int x, unsigned int y, unsigned int z)
00113     {  return (x & z) | (y & ~z);                                   }
00114     static inline unsigned int  H(unsigned int x, unsigned int y, unsigned int z)
00115     {  return x ^ y ^ z;                                            }
00116     static inline unsigned int  I(unsigned int x, unsigned int y, unsigned int z)
00117     {  return y ^ (x | ~z);                                         }
00118 
00119     // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
00120     // Rotation is separate from addition to prevent recomputation.
00121     static inline void   FF  (unsigned int& a, unsigned int b, unsigned int c, unsigned int d, unsigned int x, unsigned int s, unsigned int ac)
00122     {
00123      a += F(b, c, d) + x + ac;
00124      a = rotate_left(a, s) + b;
00125     }
00126     static inline void   GG  (unsigned int& a, unsigned int b, unsigned int c, unsigned int d, unsigned int x, unsigned int s, unsigned int ac)
00127     {
00128      a += G(b, c, d) + x + ac;
00129      a = rotate_left(a, s) + b;
00130     }
00131     static inline void   HH  (unsigned int& a, unsigned int b, unsigned int c, unsigned int d, unsigned int x, unsigned int s, unsigned int ac)
00132     {
00133      a += H(b, c, d) + x + ac;
00134      a = rotate_left(a, s) + b;
00135     }
00136     static inline void   II  (unsigned int& a, unsigned int b, unsigned int c, unsigned int d, unsigned int x, unsigned int s, unsigned int ac)
00137     {
00138      a += I(b, c, d) + x + ac;
00139      a = rotate_left(a, s) + b;
00140     }
00141   };
00142 }
00143 
00144 // MD5 simple initialization method
00145 MD5::MD5()    {
00146   init();
00147 }
00148 
00149 // MD5 simple initialization method
00150 MD5::MD5(unsigned char* buffer, unsigned long len)    {
00151   init();
00152   update(buffer, len);
00153   finalize();
00154 }
00155 
00156 // MD5 block update operation. Continues an MD5 message-digest
00157 // operation, processing another message block, and updating the
00158 // context.
00159 void MD5::update (unsigned char *input, unsigned int input_length) {
00160   unsigned int idx, index, space;
00161   if ( finalized ) {  // so we can't update!
00162     cerr << "MD5::update:  Can't update a finalized digest!" << endl;
00163     return;
00164   }
00165   // Compute number of bytes mod 64
00166   index = (unsigned int)((count[0] >> 3) & 0x3F);
00167   // Update number of bits
00168   if (  (count[0] += ((unsigned int) input_length << 3))<((unsigned int) input_length << 3) )
00169     count[1]++;
00170 
00171   count[1] += ((unsigned int)input_length >> 29);
00172   space = 64 - index;  // how much space is left in buffer
00173   // Transform as many times as possible.
00174   if (input_length >= space) { // ie. we have enough to fill the buffer
00175     // fill the rest of the buffer and transform
00176     memcpy (buffer + index, input, space);
00177     transform (buffer);
00178     // now, transform each 64-byte piece of the input, bypassing the buffer
00179     for (idx = space; idx + 63 < input_length; idx += 64)
00180       transform (input+idx);
00181 
00182     index = 0;  // so we can buffer remaining
00183   }
00184   else  {
00185     idx = 0;    // so we can buffer the whole input
00186   }
00187 
00188   // and here we do the buffering:
00189   memcpy(buffer+index, input+idx, input_length-idx);
00190 }
00191 
00192 // MD5 finalization. Ends an MD5 message-digest operation, writing the
00193 // the message digest and zeroizing the context.
00194 void MD5::finalize ()     {
00195   unsigned char bits[8];
00196   unsigned int index, padLen;
00197   static unsigned char PADDING[64]={
00198     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00199     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00200     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00201     };
00202   if (finalized){
00203     cerr << "MD5::finalize:  Already finalized this digest!" << endl;
00204     return;
00205   }
00206   // Save number of bits
00207   encode (bits, count, 8);
00208   // Pad out to 56 mod 64.
00209   index = (unsigned int) ((count[0] >> 3) & 0x3f);
00210   padLen = (index < 56) ? (56 - index) : (120 - index);
00211   update (PADDING, padLen);
00212   // Append length (before padding)
00213   update (bits, 8);
00214   // Store state in digest
00215   encode (digest, state, 16);
00216   // Zeroize sensitive information
00217   memset (buffer, 0, sizeof(*buffer));
00218   finalized=1;
00219 }
00220 
00222 void MD5::raw_digest(unsigned char *s){
00223   if (finalized){
00224     memcpy(s, digest, 16);
00225     return;
00226   }
00227   cerr << "MD5::raw_digest:  Can't get digest if you haven't "<<
00228     "finalized the digest!" << endl;
00229 }
00230 
00231 string MD5::hex_digest()   {
00232   char s[33];
00233   if (!finalized){
00234     cerr << "MD5::hex_digest:  Can't get digest if you haven't "<<
00235       "finalized the digest!" <<endl;
00236     return "";
00237   }
00238   for (int i=0; i<16; i++)
00239     sprintf(s+i*2, "%02x", digest[i]);
00240   s[32]='\0';
00241   return s;
00242 }
00243 
00244 // PRIVATE METHODS:
00245 void MD5::init(){
00246   finalized=0;  // we just started!
00247   // Nothing counted, so count=0
00248   count[0] = 0;
00249   count[1] = 0;
00250   // Load magic initialization constants.
00251   state[0] = 0x67452301;
00252   state[1] = 0xefcdab89;
00253   state[2] = 0x98badcfe;
00254   state[3] = 0x10325476;
00255 }
00256 
00257 // MD5 basic transformation. Transforms state based on block.
00258 void MD5::transform (unsigned char* block){
00259   unsigned int a = state[0], b = state[1], c = state[2], d = state[3], x[16];
00260   decode (x, block, 64);
00261   assert(!finalized);  // not just a user error, since the method is private
00262   /* Round 1                                     */
00263   FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1  */
00264   FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2  */
00265   FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3  */
00266   FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4  */
00267   FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5  */
00268   FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6  */
00269   FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7  */
00270   FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8  */
00271   FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9  */
00272   FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
00273   FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
00274   FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
00275   FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
00276   FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
00277   FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
00278   FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
00279   /* Round 2                                     */
00280   GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
00281   GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
00282   GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
00283   GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
00284   GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
00285   GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
00286   GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
00287   GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
00288   GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
00289   GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
00290   GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
00291   GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
00292   GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
00293   GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
00294   GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
00295   GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
00296   /* Round 3                                     */
00297   HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
00298   HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
00299   HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
00300   HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
00301   HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
00302   HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
00303   HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
00304   HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
00305   HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
00306   HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
00307   HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
00308   HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
00309   HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
00310   HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
00311   HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
00312   HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
00313   /* Round 4                                     */
00314   II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
00315   II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
00316   II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
00317   II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
00318   II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
00319   II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
00320   II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
00321   II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
00322   II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
00323   II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
00324   II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
00325   II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
00326   II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
00327   II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
00328   II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
00329   II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
00330   state[0] += a;
00331   state[1] += b;
00332   state[2] += c;
00333   state[3] += d;
00334   // Zeroize sensitive information.
00335   memset ( (unsigned char *) x, 0, sizeof(x));
00336 }
00337 
00338 // Encodes input (unsigned int) into output (unsigned char). Assumes len is
00339 // a multiple of 4.
00340 void MD5::encode (unsigned char *output, unsigned int *input, unsigned int len) {
00341   for (unsigned int i = 0, j = 0; j < len; i++, j += 4) {
00342     output[j]   = (unsigned char)  (input[i] & 0xff);
00343     output[j+1] = (unsigned char) ((input[i] >> 8) & 0xff);
00344     output[j+2] = (unsigned char) ((input[i] >> 16) & 0xff);
00345     output[j+3] = (unsigned char) ((input[i] >> 24) & 0xff);
00346   }
00347 }
00348 
00349 // Decodes input (unsigned char) into output (unsigned int). Assumes len is
00350 // a multiple of 4.
00351 void MD5::decode (unsigned int *output, unsigned char *input, unsigned int len){
00352   for (unsigned int i = 0, j = 0; j < len; i++, j += 4)
00353     output[i] = ((unsigned int)input[j]) | (((unsigned int)input[j+1]) << 8) |
00354       (((unsigned int)input[j+2]) << 16) | (((unsigned int)input[j+3]) << 24);
00355 }
00356 
00357 namespace cond {
00358   void* genMD5(void* buffer, unsigned long len, void* code)   {
00359     MD5 checkSum((unsigned char*)buffer, len);
00360     checkSum.raw_digest((unsigned char*)code);
00361     return code;
00362   }
00363   void genMD5(const string& s, void* code)    {
00364     MD5 checkSum((unsigned char*)s.c_str(), s.length());
00365     checkSum.raw_digest((unsigned char*)code);
00366   }
00367 }