| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

In This Package:

MD5.cpp

Go to the documentation of this file.
00001 #include "LHCbMath/MD5.h"
00002 #include <cassert>
00003 
00004 /*
00005     MD5 computation Modified from the original by Stanislav Baranov 
00006     by G.Raven for LHCb use... (09/11/2007)
00007 
00008     Copyright (C) 2002-2003 Stanislav Baranov. Permission to copy, use,
00009     modify, sell and distribute this software and its documentation is
00010     granted provided this copyright notice appears in all copies. This
00011     software is provided "as is" without express or implied warranty,
00012     and with no claim as to its suitability for any purpose. Derived
00013     from the RSA Data Security, Inc. MD5 Message-Digest Algorithm.
00014 
00015     Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights
00016     reserved. License to copy and use this software is granted provided that
00017     it is identified as the "RSA Data Security, Inc. MD5 Message-Digest
00018     Algorithm" in all material mentioning or referencing this software or
00019     this function. License is also granted to make and use derivative works
00020     provided that such works are identified as "derived from the RSA Data
00021     Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning
00022     or referencing the derived work. RSA Data Security, Inc. makes no
00023     representations concerning either the merchantability of this software
00024     or the suitability of this software for any particular purpose. It is
00025     provided "as is" without express or implied warranty of any kind. These
00026     notices must be retained in any copies of any part of this documentation
00027     and/or software.
00028 */
00029 
00030 
00031 using namespace std;
00032 
00033 /*
00034     "The [MD5] algorithm takes as input a message of arbitrary length and
00035     produces as output a 128-bit "fingerprint" or "message digest" of the
00036     input. It is conjectured that it is computationally infeasible to produce
00037     two messages having the same message digest, or to produce any message
00038     having a given prespecified target message digest. ... The MD5 algorithm
00039     is designed to be quite fast on 32-bit machines." -RFC1321
00040 */
00041 class Gaudi::Math::MD5::md5_engine
00042 {
00043 public:
00044     md5_engine() {}
00045     ~md5_engine() {}
00046 
00047 
00048     // Acquires the digest
00049     Gaudi::Math::MD5 digest(const char * a_data=0);
00050 
00051 private:
00052     // Updates the digest with additional message data.
00053     void update(const void* a_data, boost::uint32_t a_data_size);
00054 
00055     // Transforms the next message block and updates the state.
00056     void process_block(const boost::uint8_t (*a_block)[64]);
00057 
00058     boost::uint32_t state[4];
00059     boost::uint32_t count[2];   // Number of bits mod 2^64.
00060     boost::uint8_t buffer[64];  // Input buffer.
00061 };
00062 
00063 
00064 Gaudi::Math::MD5
00065 Gaudi::Math::MD5::compute(const string& s) {
00066    Gaudi::Math::MD5::md5_engine x;
00067    return x.digest( s.c_str() );
00068 }
00069 
00070 
00071 string 
00072 Gaudi::Math::MD5::str() const {
00073     string s; s.reserve(2*sizeof(value_type));
00074     for (const boost::uint8_t* i = m_value; i!=m_value+sizeof(value_type); ++i) {
00075         static const char *digits="0123456789abcdef";
00076         s+=digits[(*i>>4)&0x0F]; s+=digits[(*i)&0x0F];
00077     }
00078     return s;
00079 }
00080 
00081 namespace {
00082     boost::uint8_t unhex(unsigned char C) {
00083             unsigned char c=tolower(C);
00084             boost::uint8_t x = ( c >= '0' && c <= '9' ? c-'0' :
00085                                ( c >= 'a' && c <='f'  ? 10+(c-'a') 
00086                                                       : 255 ) );
00087             if ( x&0xF0 ) {  /* whoah: C is not in [0-9a-fA-F] */ }
00088             return x;
00089     };
00090 };
00091 
00092 Gaudi::Math::MD5
00093 Gaudi::Math::MD5::createFromStringRep(const std::string& val) { 
00094     assert(val.size()==2*sizeof(Gaudi::Math::MD5::value_type) || val.empty());
00095     if (val.empty()) return createInvalid();
00096     Gaudi::Math::MD5::value_type d;
00097     for (size_t i=0;i<sizeof(d);++i) d[i]=(unhex(val[2*i])<<4|unhex(val[2*i+1]));
00098     return MD5(d);
00099 };
00100 
00101 
00102 ostream& operator<<(ostream& os, const Gaudi::Math::MD5& x) {
00103    return os << x.str(); 
00104 }
00105 
00106 
00107 
00108 
00109 /*
00110     See http://www.boost.org for updates and documentation.
00111 
00112     Copyright (C) 2002-2003 Stanislav Baranov. Permission to copy, use,
00113     modify, sell and distribute this software and its documentation is
00114     granted provided this copyright notice appears in all copies. This
00115     software is provided "as is" without express or implied warranty,
00116     and with no claim as to its suitability for any purpose. Derived
00117     from the RSA Data Security, Inc. MD5 Message-Digest Algorithm.
00118 
00119     Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights
00120     reserved. License to copy and use this software is granted provided that
00121     it is identified as the "RSA Data Security, Inc. MD5 Message-Digest
00122     Algorithm" in all material mentioning or referencing this software or
00123     this function. License is also granted to make and use derivative works
00124     provided that such works are identified as "derived from the RSA Data
00125     Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning
00126     or referencing the derived work. RSA Data Security, Inc. makes no
00127     representations concerning either the merchantability of this software
00128     or the suitability of this software for any particular purpose. It is
00129     provided "as is" without express or implied warranty of any kind. These
00130     notices must be retained in any copies of any part of this documentation
00131     and/or software.
00132 */
00133 
00134 
00135 
00136 namespace
00137 {
00138 
00139     /*
00140         Pack/unpack between arrays of uint8_t and uint32_t in
00141         a platform-independent way. Size is a multiple of 4.
00142     */
00143 
00144     void pack(boost::uint8_t* dst, const boost::uint32_t* src, boost::uint32_t size) {
00145         boost::uint32_t i(0);
00146         boost::uint32_t j(0);
00147 
00148         while (j < size) {
00149             dst[j+0] = static_cast<boost::uint8_t>((src[i] >>  0) & 0xff);
00150             dst[j+1] = static_cast<boost::uint8_t>((src[i] >>  8) & 0xff);
00151             dst[j+2] = static_cast<boost::uint8_t>((src[i] >> 16) & 0xff);
00152             dst[j+3] = static_cast<boost::uint8_t>((src[i] >> 24) & 0xff);
00153             ++i;
00154             j += 4;
00155         }
00156     }
00157 
00158     void unpack(boost::uint32_t* dst, const boost::uint8_t* src, boost::uint32_t size) {
00159         boost::uint32_t i(0);
00160         boost::uint32_t j(0);
00161 
00162         while (j < size) {
00163             dst[i] =
00164                 (static_cast<boost::uint32_t>(src[j+0]) <<  0) |
00165                 (static_cast<boost::uint32_t>(src[j+1]) <<  8) |
00166                 (static_cast<boost::uint32_t>(src[j+2]) << 16) |
00167                 (static_cast<boost::uint32_t>(src[j+3]) << 24);
00168             ++i;
00169             j += 4;
00170         }
00171     }
00172 
00173 
00174     const boost::uint32_t S11(7);
00175     const boost::uint32_t S12(12);
00176     const boost::uint32_t S13(17);
00177     const boost::uint32_t S14(22);
00178     const boost::uint32_t S21(5);
00179     const boost::uint32_t S22(9);
00180     const boost::uint32_t S23(14);
00181     const boost::uint32_t S24(20);
00182     const boost::uint32_t S31(4);
00183     const boost::uint32_t S32(11);
00184     const boost::uint32_t S33(16);
00185     const boost::uint32_t S34(23);
00186     const boost::uint32_t S41(6);
00187     const boost::uint32_t S42(10);
00188     const boost::uint32_t S43(15);
00189     const boost::uint32_t S44(21);
00190 
00191     inline boost::uint32_t rol(boost::uint32_t x, boost::uint32_t n_bits) { return (x << n_bits) | (x >> (32-n_bits)); }
00192 
00193     /*
00194         Basic MD5 functions.
00195     */
00196 
00197     inline boost::uint32_t F(boost::uint32_t x, boost::uint32_t y, boost::uint32_t z) { return (x & y) | (~x & z); }
00198     inline boost::uint32_t G(boost::uint32_t x, boost::uint32_t y, boost::uint32_t z) { return (x & z) | (y & ~z); }
00199     inline boost::uint32_t H(boost::uint32_t x, boost::uint32_t y, boost::uint32_t z) { return x ^ y ^ z; }
00200     inline boost::uint32_t I(boost::uint32_t x, boost::uint32_t y, boost::uint32_t z) { return y ^ (x | ~z); }
00201 
00202     /*
00203         Transformations for rounds 1, 2, 3, and 4.
00204     */
00205 
00206     inline void FF(boost::uint32_t& a, boost::uint32_t b, boost::uint32_t c, boost::uint32_t d, boost::uint32_t x, boost::uint32_t  s, boost::uint32_t ac)
00207     {
00208         a += F(b, c, d) + x + ac;
00209         a = rol(a, s) + b;
00210     }
00211 
00212     inline void GG(boost::uint32_t& a, boost::uint32_t b, boost::uint32_t c, boost::uint32_t d, boost::uint32_t x, boost::uint32_t s, boost::uint32_t ac)
00213     {
00214         a += G(b, c, d) + x + ac;
00215         a = rol(a, s) + b;
00216     }
00217 
00218     inline void HH(boost::uint32_t& a, boost::uint32_t b, boost::uint32_t c, boost::uint32_t d, boost::uint32_t x, boost::uint32_t s, boost::uint32_t ac)
00219     {
00220         a += H(b, c, d) + x + ac;
00221         a = rol(a, s) + b;
00222     }
00223 
00224     inline void II(boost::uint32_t& a, boost::uint32_t b, boost::uint32_t c, boost::uint32_t d, boost::uint32_t x, boost::uint32_t s, boost::uint32_t ac)
00225     {
00226         a += I(b, c, d) + x + ac;
00227         a = rol(a, s) + b;
00228     }
00229 }
00230 
00231 
00232 void Gaudi::Math::MD5::md5_engine::update(const void* a_data, boost::uint32_t a_data_size)
00233 {
00234     // Compute number of bytes mod 64.
00235     boost::uint32_t buffer_index = static_cast<boost::uint32_t>((count[0] >> 3) & 0x3f);
00236 
00237     // Update number of bits.
00238     count[0] += (static_cast<boost::uint32_t>(a_data_size) << 3);
00239     if (count[0] < (static_cast<boost::uint32_t>(a_data_size) << 3))
00240         ++count[1];
00241 
00242     count[1] += (static_cast<boost::uint32_t>(a_data_size) >> 29);
00243 
00244     boost::uint32_t buffer_space = 64-buffer_index;  // Remaining buffer space.
00245 
00246     boost::uint32_t input_index;
00247 
00248     // Transform as many times as possible.
00249     if (a_data_size >= buffer_space) {
00250         memcpy(buffer+buffer_index, a_data, buffer_space);
00251         process_block(&buffer);
00252 
00253         for (input_index = buffer_space; input_index+63 < a_data_size; input_index += 64) {
00254             process_block(reinterpret_cast<const boost::uint8_t (*)[64]>(
00255                 reinterpret_cast<const boost::uint8_t*>(a_data)+input_index));
00256         }
00257 
00258         buffer_index = 0;
00259     } else {
00260         input_index = 0;
00261     }
00262 
00263     // Buffer remaining input.
00264     memcpy(buffer+buffer_index, reinterpret_cast<
00265         const boost::uint8_t*>(a_data)+input_index, a_data_size-input_index);
00266 }
00267 
00268 Gaudi::Math::MD5 Gaudi::Math::MD5::md5_engine::digest(const char * a_data)
00269 {
00270     count[0] = 0;
00271     count[1] = 0;
00272 
00273     state[0] = 0x67452301;
00274     state[1] = 0xefcdab89;
00275     state[2] = 0x98badcfe;
00276     state[3] = 0x10325476;
00277 
00278     if (a_data!=0) update(a_data,strlen(a_data));
00279 
00280     
00281     static const boost::uint8_t padding[64] =
00282     {
00283         0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00284         0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00285         0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00286         0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00287     };
00288 
00289     // Save number of bits.
00290     boost::uint8_t saved_count[8];
00291     pack(saved_count, count, 8);
00292 
00293     // Pad out to 56 mod 64.
00294     boost::uint32_t index = static_cast<boost::uint32_t>((count[0] >> 3) & 0x3f);
00295     boost::uint32_t padding_size = (index < 56) ? (56 - index) : (120 - index);
00296     update(padding, padding_size);
00297 
00298     // Append size before padding.
00299     update(saved_count, 8);
00300 
00301     // Store state in digest.
00302     MD5::value_type digest;
00303     pack(digest, state, sizeof(digest));
00304     return MD5(digest);
00305 }
00306 
00307 
00308 
00309 void Gaudi::Math::MD5::md5_engine::process_block(const boost::uint8_t (*a_block)[64])
00310 {
00311     boost::uint32_t a(state[0]);
00312     boost::uint32_t b(state[1]);
00313     boost::uint32_t c(state[2]);
00314     boost::uint32_t d(state[3]);
00315 
00316     /*volatile*/ boost::uint32_t x[16];
00317 
00318     unpack(x, reinterpret_cast<const boost::uint8_t*>(a_block), 64);
00319 
00320     // Round 1.
00321     FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /*  1 */
00322     FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /*  2 */
00323     FF(c, d, a, b, x[ 2], S13, 0x242070db); /*  3 */
00324     FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /*  4 */
00325     FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /*  5 */
00326     FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /*  6 */
00327     FF(c, d, a, b, x[ 6], S13, 0xa8304613); /*  7 */
00328     FF(b, c, d, a, x[ 7], S14, 0xfd469501); /*  8 */
00329     FF(a, b, c, d, x[ 8], S11, 0x698098d8); /*  9 */
00330     FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
00331     FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
00332     FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
00333     FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
00334     FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
00335     FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
00336     FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
00337 
00338     // Round 2.
00339     GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
00340     GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
00341     GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
00342     GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
00343     GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
00344     GG(d, a, b, c, x[10], S22,  0x2441453); /* 22 */
00345     GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
00346     GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
00347     GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
00348     GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
00349     GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
00350     GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
00351     GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
00352     GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
00353     GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
00354     GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
00355 
00356     // Round 3.
00357     HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
00358     HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
00359     HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
00360     HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
00361     HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
00362     HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
00363     HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
00364     HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
00365     HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
00366     HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
00367     HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
00368     HH(b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
00369     HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
00370     HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
00371     HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
00372     HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
00373 
00374     // Round 4.
00375     II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
00376     II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
00377     II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
00378     II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
00379     II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
00380     II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
00381     II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
00382     II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
00383     II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
00384     II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
00385     II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
00386     II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
00387     II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
00388     II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
00389     II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
00390     II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
00391 
00392     state[0] += a;
00393     state[1] += b;
00394     state[2] += c;
00395     state[3] += d;
00396 
00397     // Zeroize sensitive information.
00398     memset(reinterpret_cast<boost::uint8_t*>(x), 0, sizeof(x));
00399 }
| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

Generated on Mon Apr 11 20:02:57 2011 for LHCbMath by doxygen 1.4.7