md5.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright, 2000, 2001, 2002,2003,2004 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
00022  */
00023 
00024 
00025 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
00026  */
00027 
00028 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
00029    rights reserved.
00030 
00031    License to copy and use this software is granted provided that it
00032    is identified as the "RSA Data Security, Inc. MD5 Message-Digest
00033 Algorithm" in all material mentioning or referencing this software
00034 or this function.
00035 
00036 License is also granted to make and use derivative works provided
00037 that such works are identified as "derived from the RSA Data
00038 Security, Inc. MD5 Message-Digest Algorithm" in all material
00039 mentioning or referencing the derived work.
00040 
00041 RSA Data Security, Inc. makes no representations concerning either
00042 the merchantability of this software or the suitability of this
00043 software for any particular purpose. It is provided "as is"
00044 without express or implied warranty of any kind.
00045 
00046 These notices must be retained in any copies of any part of this
00047 documentation and/or software.
00048 */
00049 
00050 #include "stdmisc.h"
00051 
00052 #include "nel/misc/md5.h"
00053 
00054 #include "nel/misc/types_nl.h"
00055 #include "nel/misc/debug.h"
00056 #include "nel/misc/file.h"
00057 #include "nel/misc/path.h"
00058 #include "nel/misc/stream.h"
00059 
00060 using namespace std;
00061 
00062 namespace NLMISC
00063 {
00064 // ****************************************************************************
00065 // ****************************************************************************
00066 // High Level Routines
00067 // ****************************************************************************
00068 // ****************************************************************************
00069 
00070 // ****************************************************************************
00071 CHashKeyMD5 getMD5(const std::string &filename)
00072 {
00073     CMD5Context md5ctx;
00074     CHashKeyMD5 Message_Digest;
00075     Message_Digest.clear();
00076 
00077     CIFile ifile;
00078     if (!ifile.open(CPath::lookup(filename)))
00079     {
00080         nlwarning ("MD5: Can't open the file '%s'", filename.c_str());
00081         return Message_Digest;
00082     }
00083 
00084     md5ctx.init();
00085 
00086     uint8 buffer[1024];
00087     int bufferSize = 1024;
00088     sint fs = ifile.getFileSize();
00089     sint n, read = 0;
00090     do
00091     {
00092         //bs = (int)fread (buffer, 1, bufferSize, fp);
00093         n = std::min (bufferSize, fs-read);
00094         //nlinfo ("read %d bytes", n);
00095         ifile.serialBuffer((uint8 *)buffer, n);
00096 
00097         md5ctx.update(buffer, n);
00098 
00099         read += n;
00100     }
00101     while (!ifile.eof());
00102 
00103     ifile.close ();
00104 
00105     md5ctx.final(Message_Digest);
00106 
00107     return Message_Digest;
00108 }
00109 
00110 // ****************************************************************************
00111 CHashKeyMD5 getMD5(const uint8 *buffer, uint32 size)
00112 {
00113     CMD5Context md5ctx;
00114     CHashKeyMD5 Message_Digest;
00115     Message_Digest.clear();
00116 
00117     md5ctx.init();
00118     md5ctx.update(buffer, size);
00119     md5ctx.final(Message_Digest);
00120 
00121     return Message_Digest;
00122 }
00123 
00124 // ****************************************************************************
00125 // Helper
00126 // ****************************************************************************
00127 static bool fromHex(char c, uint8 &x)
00128 {
00129     if (c >= '0' && c <= '9')
00130     {
00131         x = c - '0';
00132         return true;
00133     }
00134     else if (c >= 'A' && c <= 'F')
00135     {
00136         x = c - 'A' + 10;
00137         return true;
00138     }
00139     else if (c >= 'a' && c <= 'f')
00140     {
00141         x = c - 'a' + 10;
00142         return true;
00143     }
00144 
00145     nlwarning("cannot convert to hexa");
00146     return false;
00147 }
00148 
00149 // ****************************************************************************
00150 // ****************************************************************************
00151 // CHashKeyMD5
00152 // ****************************************************************************
00153 // ****************************************************************************
00154 
00155 // ****************************************************************************
00156 void CHashKeyMD5::clear()
00157 {
00158     for (uint32 i = 0; i < 16; ++i)
00159         Data[i] = 0;
00160 }
00161 
00162 // ****************************************************************************
00163 string CHashKeyMD5::toString() const
00164 {
00165     string sTmp;
00166     for (uint32 i = 0; i < 16; ++i)
00167         sTmp += NLMISC::toString("%02x", Data[i]);
00168     return sTmp;
00169 }
00170 
00171 // ****************************************************************************
00172 bool CHashKeyMD5::fromString(const std::string &in)
00173 {
00174     if (in.size() != 32)
00175     {
00176         nlwarning("bad string size");
00177         return false;
00178     }
00179 
00180     for (uint32 i = 0; i < 16; ++i)
00181     {
00182         char c1 = in[2*i];
00183         char c2 = in[2*i+1];
00184         uint8 x1, x2;
00185         if (!fromHex(c1, x1)) return false;
00186         if (!fromHex(c2, x2)) return false;
00187         Data[i] = (x1 << 4) | x2;
00188     }
00189     return true;
00190 }
00191 
00192 // ****************************************************************************
00193 bool CHashKeyMD5::operator!=(const CHashKeyMD5 &in) const
00194 {
00195     for (uint32 i = 0; i < 16; ++i)
00196         if (Data[i] != in.Data[i])
00197             return true;
00198     return false;
00199 }
00200 
00201 // ****************************************************************************
00202 bool CHashKeyMD5::operator==(const CHashKeyMD5 &in) const
00203 {
00204     return !operator!=(in);
00205 }
00206 
00207 // ****************************************************************************
00208 bool CHashKeyMD5::operator<(const CHashKeyMD5 &in) const
00209 {
00210     for (uint32 i = 0; i < 16; ++i)
00211         if (Data[i] >= in.Data[i])
00212             return false;
00213     return true;
00214 }
00215 
00216 // ****************************************************************************
00217 void CHashKeyMD5::serial (NLMISC::IStream &s)
00218 {
00219     s.serialBuffer(Data,16);
00220 }
00221 
00222 
00223 // ****************************************************************************
00224 // ****************************************************************************
00225 // CMD5Context
00226 // ****************************************************************************
00227 // ****************************************************************************
00228 
00229 uint8 CMD5Context::Padding[64] = {
00230     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00231     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00232     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00233 };
00234 
00235 // ****************************************************************************
00236 void CMD5Context::init()
00237 {
00238     Count[0] = Count[1] = 0;
00239     // Load magic initialization constants.
00240     State[0] = 0x67452301;
00241     State[1] = 0xefcdab89;
00242     State[2] = 0x98badcfe;
00243     State[3] = 0x10325476;
00244 }
00245 
00246 // ****************************************************************************
00247 void CMD5Context::update (const uint8 *pBufIn, uint32 nBufLength)
00248 {
00249     uint i, index, partLen;
00250 
00251     // Compute number of bytes mod 64
00252     index = (uint)((Count[0] >> 3) & 0x3F);
00253 
00254     // Update number of bits
00255     if ((Count[0] += (nBufLength << 3)) < (nBufLength << 3))
00256     Count[1]++;
00257     Count[1] += (nBufLength >> 29);
00258 
00259     partLen = 64 - index;
00260 
00261     // Transform as many times as possible.
00262     if (nBufLength >= partLen)
00263     {
00264         memcpy((uint8*)&Buffer[index], pBufIn, partLen);
00265         transform (State, Buffer);
00266 
00267         for (i = partLen; i + 63 < nBufLength; i += 64)
00268             transform (State, &pBufIn[i]);
00269 
00270         index = 0;
00271     }
00272     else
00273     {
00274         i = 0;
00275     }
00276 
00277     // Buffer remaining input
00278     memcpy((uint8*)&Buffer[index], &pBufIn[i], nBufLength-i);
00279 }
00280 
00281 // ****************************************************************************
00282 void CMD5Context::final (CHashKeyMD5 &out)
00283 {
00284     uint8 bits[8];
00285     uint index, padLen;
00286 
00287     // Save number of bits
00288     encode (&bits[0], Count, 8);
00289 
00290     // Pad out to 56 mod 64.
00291     index = (unsigned int)((Count[0] >> 3) & 0x3f);
00292     padLen = (index < 56) ? (56 - index) : (120 - index);
00293     update (Padding, padLen);
00294 
00295     // Append length (before padding)
00296     update (&bits[0], 8);
00297     // Store state in digest
00298     encode (out.Data, State, 16);
00299 
00300     // Zeroize sensitive information.
00301     uint i;
00302     for (i = 0; i < 4; ++i) State[i] = 0;
00303     for (i = 0; i < 2; ++i) Count[i] = 0;
00304     for (i = 0; i < 64; ++i) Buffer[i] = 0;
00305 }
00306 
00307 // Constants for MD5Transform routine.
00308 // ****************************************************************************
00309 #define S11 7
00310 #define S12 12
00311 #define S13 17
00312 #define S14 22
00313 #define S21 5
00314 #define S22 9
00315 #define S23 14
00316 #define S24 20
00317 #define S31 4
00318 #define S32 11
00319 #define S33 16
00320 #define S34 23
00321 #define S41 6
00322 #define S42 10
00323 #define S43 15
00324 #define S44 21
00325 
00326 // F, G, H and I are basic MD5 functions.
00327 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
00328 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
00329 #define H(x, y, z) ((x) ^ (y) ^ (z))
00330 #define I(x, y, z) ((y) ^ ((x) | (~z)))
00331 
00332 // ROTATE_LEFT rotates x left n bits.
00333 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
00334 
00335 // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
00336 // Rotation is separate from addition to prevent recomputation.
00337 #define FF(a, b, c, d, x, s, ac) { \
00338       (a) += F ((b), (c), (d)) + (x) + (uint32)(ac); \
00339       (a) = ROTATE_LEFT ((a), (s)); \
00340       (a) += (b); \
00341                    }
00342 #define GG(a, b, c, d, x, s, ac) { \
00343       (a) += G ((b), (c), (d)) + (x) + (uint32)(ac); \
00344       (a) = ROTATE_LEFT ((a), (s)); \
00345       (a) += (b); \
00346      }
00347 #define HH(a, b, c, d, x, s, ac) { \
00348       (a) += H ((b), (c), (d)) + (x) + (uint32)(ac); \
00349       (a) = ROTATE_LEFT ((a), (s)); \
00350       (a) += (b); \
00351      }
00352 #define II(a, b, c, d, x, s, ac) { \
00353       (a) += I ((b), (c), (d)) + (x) + (uint32)(ac); \
00354       (a) = ROTATE_LEFT ((a), (s)); \
00355       (a) += (b); \
00356      }
00357 
00358 
00359 // MD5 basic transformation. Transforms state based on block.
00360 // ****************************************************************************
00361 void CMD5Context::transform (uint32 state[4], const uint8 block[64])
00362 {
00363     uint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
00364 
00365     decode (&x[0], &block[0], 64);
00366 
00367     // Round 1
00368     FF (a, b, c, d, x[ 0], S11, 0xd76aa478); // 1
00369     FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); // 2
00370     FF (c, d, a, b, x[ 2], S13, 0x242070db); // 3
00371     FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); // 4
00372     FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); // 5
00373     FF (d, a, b, c, x[ 5], S12, 0x4787c62a); // 6
00374     FF (c, d, a, b, x[ 6], S13, 0xa8304613); // 7
00375     FF (b, c, d, a, x[ 7], S14, 0xfd469501); // 8
00376     FF (a, b, c, d, x[ 8], S11, 0x698098d8); // 9
00377     FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); // 10
00378     FF (c, d, a, b, x[10], S13, 0xffff5bb1); // 11
00379     FF (b, c, d, a, x[11], S14, 0x895cd7be); // 12
00380     FF (a, b, c, d, x[12], S11, 0x6b901122); // 13
00381     FF (d, a, b, c, x[13], S12, 0xfd987193); // 14
00382     FF (c, d, a, b, x[14], S13, 0xa679438e); // 15
00383     FF (b, c, d, a, x[15], S14, 0x49b40821); // 16
00384 
00385     // Round 2
00386     GG (a, b, c, d, x[ 1], S21, 0xf61e2562); // 17
00387     GG (d, a, b, c, x[ 6], S22, 0xc040b340); // 18
00388     GG (c, d, a, b, x[11], S23, 0x265e5a51); // 19
00389     GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); // 20
00390     GG (a, b, c, d, x[ 5], S21, 0xd62f105d); // 21
00391     GG (d, a, b, c, x[10], S22,  0x2441453); // 22
00392     GG (c, d, a, b, x[15], S23, 0xd8a1e681); // 23
00393     GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); // 24
00394     GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); // 25
00395     GG (d, a, b, c, x[14], S22, 0xc33707d6); // 26
00396     GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); // 27
00397     GG (b, c, d, a, x[ 8], S24, 0x455a14ed); // 28
00398     GG (a, b, c, d, x[13], S21, 0xa9e3e905); // 29
00399     GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); // 30
00400     GG (c, d, a, b, x[ 7], S23, 0x676f02d9); // 31
00401     GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); // 32
00402 
00403     // Round 3
00404     HH (a, b, c, d, x[ 5], S31, 0xfffa3942); // 33
00405     HH (d, a, b, c, x[ 8], S32, 0x8771f681); // 34
00406     HH (c, d, a, b, x[11], S33, 0x6d9d6122); // 35
00407     HH (b, c, d, a, x[14], S34, 0xfde5380c); // 36
00408     HH (a, b, c, d, x[ 1], S31, 0xa4beea44); // 37
00409     HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); // 38
00410     HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); // 39
00411     HH (b, c, d, a, x[10], S34, 0xbebfbc70); // 40
00412     HH (a, b, c, d, x[13], S31, 0x289b7ec6); // 41
00413     HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); // 42
00414     HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); // 43
00415     HH (b, c, d, a, x[ 6], S34,  0x4881d05); // 44
00416     HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); // 45
00417     HH (d, a, b, c, x[12], S32, 0xe6db99e5); // 46
00418     HH (c, d, a, b, x[15], S33, 0x1fa27cf8); // 47
00419     HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); // 48
00420 
00421     // Round 4
00422     II (a, b, c, d, x[ 0], S41, 0xf4292244); // 49
00423     II (d, a, b, c, x[ 7], S42, 0x432aff97); // 50
00424     II (c, d, a, b, x[14], S43, 0xab9423a7); // 51
00425     II (b, c, d, a, x[ 5], S44, 0xfc93a039); // 52
00426     II (a, b, c, d, x[12], S41, 0x655b59c3); // 53
00427     II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); // 54
00428     II (c, d, a, b, x[10], S43, 0xffeff47d); // 55
00429     II (b, c, d, a, x[ 1], S44, 0x85845dd1); // 56
00430     II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); // 57
00431     II (d, a, b, c, x[15], S42, 0xfe2ce6e0); // 58
00432     II (c, d, a, b, x[ 6], S43, 0xa3014314); // 59
00433     II (b, c, d, a, x[13], S44, 0x4e0811a1); // 60
00434     II (a, b, c, d, x[ 4], S41, 0xf7537e82); // 61
00435     II (d, a, b, c, x[11], S42, 0xbd3af235); // 62
00436     II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); // 63
00437     II (b, c, d, a, x[ 9], S44, 0xeb86d391); // 64
00438 
00439     state[0] += a;
00440     state[1] += b;
00441     state[2] += c;
00442     state[3] += d;
00443 }
00444 
00445 // Encodes input (guint32) into output (unsigned char). Assumes len is a multiple of 4.
00446 // ****************************************************************************
00447 void CMD5Context::encode (uint8 *output, const uint32 *input, uint len)
00448 {
00449     uint i, j;
00450 
00451     for (i = 0, j = 0; j < len; i++, j += 4)
00452     {
00453         output[j] = (uint8)(input[i] & 0xff);
00454         output[j+1] = (uint8)((input[i] >> 8) & 0xff);
00455         output[j+2] = (uint8)((input[i] >> 16) & 0xff);
00456         output[j+3] = (uint8)((input[i] >> 24) & 0xff);
00457     }
00458 }
00459 
00460 // Decodes input (unsigned char) into output (guint32). Assumes len is a multiple of 4.
00461 // ****************************************************************************
00462 void CMD5Context::decode (uint32 *output, const uint8 *input, uint len)
00463 {
00464     uint i, j;
00465 
00466     for (i = 0, j = 0; j < len; i++, j += 4)
00467         output[i] = ((uint32)input[j]) | (((uint32)input[j+1]) << 8) |
00468                     (((uint32)input[j+2]) << 16) | (((uint32)input[j+3]) << 24);
00469 }
00470 
00471 
00472 } // namespace NLMISC
00473 

Generated on Thu Jan 7 08:26:34 2010 for NeL by  doxygen 1.6.1