00001 #include "LHCbMath/MD5.h"
00002 #include <cassert>
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 using namespace std;
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 class Gaudi::Math::MD5::md5_engine
00042 {
00043 public:
00044 md5_engine() {}
00045 ~md5_engine() {}
00046
00047
00048
00049 Gaudi::Math::MD5 digest(const char * a_data=0);
00050
00051 private:
00052
00053 void update(const void* a_data, boost::uint32_t a_data_size);
00054
00055
00056 void process_block(const boost::uint8_t (*a_block)[64]);
00057
00058 boost::uint32_t state[4];
00059 boost::uint32_t count[2];
00060 boost::uint8_t buffer[64];
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 ) { }
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
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 namespace
00137 {
00138
00139
00140
00141
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
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
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
00235 boost::uint32_t buffer_index = static_cast<boost::uint32_t>((count[0] >> 3) & 0x3f);
00236
00237
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;
00245
00246 boost::uint32_t input_index;
00247
00248
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
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
00290 boost::uint8_t saved_count[8];
00291 pack(saved_count, count, 8);
00292
00293
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
00299 update(saved_count, 8);
00300
00301
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 boost::uint32_t x[16];
00317
00318 unpack(x, reinterpret_cast<const boost::uint8_t*>(a_block), 64);
00319
00320
00321 FF(a, b, c, d, x[ 0], S11, 0xd76aa478);
00322 FF(d, a, b, c, x[ 1], S12, 0xe8c7b756);
00323 FF(c, d, a, b, x[ 2], S13, 0x242070db);
00324 FF(b, c, d, a, x[ 3], S14, 0xc1bdceee);
00325 FF(a, b, c, d, x[ 4], S11, 0xf57c0faf);
00326 FF(d, a, b, c, x[ 5], S12, 0x4787c62a);
00327 FF(c, d, a, b, x[ 6], S13, 0xa8304613);
00328 FF(b, c, d, a, x[ 7], S14, 0xfd469501);
00329 FF(a, b, c, d, x[ 8], S11, 0x698098d8);
00330 FF(d, a, b, c, x[ 9], S12, 0x8b44f7af);
00331 FF(c, d, a, b, x[10], S13, 0xffff5bb1);
00332 FF(b, c, d, a, x[11], S14, 0x895cd7be);
00333 FF(a, b, c, d, x[12], S11, 0x6b901122);
00334 FF(d, a, b, c, x[13], S12, 0xfd987193);
00335 FF(c, d, a, b, x[14], S13, 0xa679438e);
00336 FF(b, c, d, a, x[15], S14, 0x49b40821);
00337
00338
00339 GG(a, b, c, d, x[ 1], S21, 0xf61e2562);
00340 GG(d, a, b, c, x[ 6], S22, 0xc040b340);
00341 GG(c, d, a, b, x[11], S23, 0x265e5a51);
00342 GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa);
00343 GG(a, b, c, d, x[ 5], S21, 0xd62f105d);
00344 GG(d, a, b, c, x[10], S22, 0x2441453);
00345 GG(c, d, a, b, x[15], S23, 0xd8a1e681);
00346 GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8);
00347 GG(a, b, c, d, x[ 9], S21, 0x21e1cde6);
00348 GG(d, a, b, c, x[14], S22, 0xc33707d6);
00349 GG(c, d, a, b, x[ 3], S23, 0xf4d50d87);
00350 GG(b, c, d, a, x[ 8], S24, 0x455a14ed);
00351 GG(a, b, c, d, x[13], S21, 0xa9e3e905);
00352 GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8);
00353 GG(c, d, a, b, x[ 7], S23, 0x676f02d9);
00354 GG(b, c, d, a, x[12], S24, 0x8d2a4c8a);
00355
00356
00357 HH(a, b, c, d, x[ 5], S31, 0xfffa3942);
00358 HH(d, a, b, c, x[ 8], S32, 0x8771f681);
00359 HH(c, d, a, b, x[11], S33, 0x6d9d6122);
00360 HH(b, c, d, a, x[14], S34, 0xfde5380c);
00361 HH(a, b, c, d, x[ 1], S31, 0xa4beea44);
00362 HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9);
00363 HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60);
00364 HH(b, c, d, a, x[10], S34, 0xbebfbc70);
00365 HH(a, b, c, d, x[13], S31, 0x289b7ec6);
00366 HH(d, a, b, c, x[ 0], S32, 0xeaa127fa);
00367 HH(c, d, a, b, x[ 3], S33, 0xd4ef3085);
00368 HH(b, c, d, a, x[ 6], S34, 0x4881d05);
00369 HH(a, b, c, d, x[ 9], S31, 0xd9d4d039);
00370 HH(d, a, b, c, x[12], S32, 0xe6db99e5);
00371 HH(c, d, a, b, x[15], S33, 0x1fa27cf8);
00372 HH(b, c, d, a, x[ 2], S34, 0xc4ac5665);
00373
00374
00375 II(a, b, c, d, x[ 0], S41, 0xf4292244);
00376 II(d, a, b, c, x[ 7], S42, 0x432aff97);
00377 II(c, d, a, b, x[14], S43, 0xab9423a7);
00378 II(b, c, d, a, x[ 5], S44, 0xfc93a039);
00379 II(a, b, c, d, x[12], S41, 0x655b59c3);
00380 II(d, a, b, c, x[ 3], S42, 0x8f0ccc92);
00381 II(c, d, a, b, x[10], S43, 0xffeff47d);
00382 II(b, c, d, a, x[ 1], S44, 0x85845dd1);
00383 II(a, b, c, d, x[ 8], S41, 0x6fa87e4f);
00384 II(d, a, b, c, x[15], S42, 0xfe2ce6e0);
00385 II(c, d, a, b, x[ 6], S43, 0xa3014314);
00386 II(b, c, d, a, x[13], S44, 0x4e0811a1);
00387 II(a, b, c, d, x[ 4], S41, 0xf7537e82);
00388 II(d, a, b, c, x[11], S42, 0xbd3af235);
00389 II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb);
00390 II(b, c, d, a, x[ 9], S44, 0xeb86d391);
00391
00392 state[0] += a;
00393 state[1] += b;
00394 state[2] += c;
00395 state[3] += d;
00396
00397
00398 memset(reinterpret_cast<boost::uint8_t*>(x), 0, sizeof(x));
00399 }