OW_MD5.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2001-2004 Vintela, Inc. All rights reserved.
00003 *
00004 * Redistribution and use in source and binary forms, with or without
00005 * modification, are permitted provided that the following conditions are met:
00006 *
00007 *  - Redistributions of source code must retain the above copyright notice,
00008 *    this list of conditions and the following disclaimer.
00009 *
00010 *  - Redistributions in binary form must reproduce the above copyright notice,
00011 *    this list of conditions and the following disclaimer in the documentation
00012 *    and/or other materials provided with the distribution.
00013 *
00014 *  - Neither the name of Vintela, Inc. nor the names of its
00015 *    contributors may be used to endorse or promote products derived from this
00016 *    software without specific prior written permission.
00017 *
00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc. OR THE CONTRIBUTORS
00022 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028 * POSSIBILITY OF SUCH DAMAGE.
00029 *******************************************************************************/
00030 
00036 #include "OW_config.h"
00037 #include "OW_MD5.hpp"
00038 #include "OW_String.hpp"
00039 #include "OW_ExceptionIds.hpp"
00040 
00041 #include <string.h> // for memset
00042 
00043 #ifdef OW_WIN32
00044 #pragma warning (push)
00045 #pragma warning (disable: 4355)
00046 #endif
00047 
00048 namespace OW_NAMESPACE
00049 {
00050 
00051 const int MD5HASHHEXLEN = 32;
00052 
00053 OW_DEFINE_EXCEPTION_WITH_ID(MD5);
00055 MD5OStreamBase::MD5OStreamBase(MD5* md5): _buf(md5) {}
00057 MD5StreamBuffer::MD5StreamBuffer(MD5* md5): _md5(md5) {}
00059 int 
00060 MD5StreamBuffer::overflow(int c)
00061 {
00062    unsigned char lc = c;
00063    MD5::MD5Update(&(_md5->m_ctx), &lc, 1);
00064    return c;
00065 }
00067 std::streamsize 
00068 MD5StreamBuffer::xsputn(const char* s, std::streamsize num)
00069 {
00070    MD5::MD5Update(&(_md5->m_ctx), 
00071                      reinterpret_cast<const unsigned char*>(s), num);
00072    return num;
00073 }
00075 MD5::MD5()
00076 : MD5OStreamBase(this), std::ostream(&_buf), m_ctx(), m_finished(false)
00077 {
00078    MD5Init(&m_ctx);
00079 }
00081 void
00082 MD5::init(const String& input)
00083 {
00084    m_finished = false;
00085    MD5Init(&m_ctx);
00086    update(input);
00087 }
00089 MD5::MD5(const String& input)
00090 : MD5OStreamBase(this), std::ostream(&_buf), m_ctx(), m_finished(false)
00091 {
00092    MD5Init(&m_ctx);
00093    update(input);
00094 }
00096 void
00097 MD5::update(const String& input)
00098 {
00099    if (m_finished)
00100    {
00101       OW_THROW(MD5Exception, "Cannot update after a call to toString()");
00102    }
00103    MD5Update(&m_ctx, reinterpret_cast<const unsigned char*>(input.c_str()), 
00104              input.length());
00105 }
00107 String
00108 MD5::toString()
00109 {
00110    return convertBinToHex(getDigest());
00111 }
00113 unsigned char*
00114 MD5::getDigest()
00115 {
00116    if (!m_finished)
00117    {
00118       MD5Final(m_digest, &m_ctx);
00119       m_finished = true;
00120    }
00121    return m_digest;
00122 }
00124 String
00125 MD5::convertBinToHex( const unsigned char* sBin)
00126 {
00127    unsigned short i;
00128    unsigned char j;
00129    char Hex[ MD5HASHHEXLEN + 1 ];
00130    for ( i = 0; i < MD5HASHLEN; i++ )
00131    {
00132       j = (sBin[i] >> 4) & 0xf;
00133       if ( j <= 9 )
00134       {
00135          Hex[i*2] = (j + '0');
00136       }
00137       else
00138       {
00139          Hex[i*2] = (j + 'a' - 10);
00140       }
00141       j = sBin[i] & 0xf;
00142       if ( j <= 9 )
00143       {
00144          Hex[i*2+1] = (j + '0');
00145       }
00146       else
00147       {
00148          Hex[i*2+1] = (j + 'a' - 10);
00149       }
00150    };
00151    Hex[MD5HASHHEXLEN] = '\0';
00152    return String(Hex);
00153 };
00154 //A.3 md5c.c
00155 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
00156  */
00157 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
00158 rights reserved.
00159 License to copy and use this software is granted provided that it
00160 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
00161 Algorithm" in all material mentioning or referencing this software
00162 or this function.
00163 License is also granted to make and use derivative works provided
00164 that such works are identified as "derived from the RSA Data
00165 Security, Inc. MD5 Message-Digest Algorithm" in all material
00166 mentioning or referencing the derived work.
00167 RSA Data Security, Inc. makes no representations concerning either
00168 the merchantability of this software or the suitability of this
00169 software for any particular purpose. It is provided "as is"
00170 without express or implied warranty of any kind.
00171 These notices must be retained in any copies of any part of this
00172 documentation and/or software.
00173  */
00174 /* POINTER defines a generic pointer type */
00175 typedef unsigned char *POINTER;
00176 /* Constants for MD5Transform routine.
00177  */
00178 #define S11 7
00179 #define S12 12
00180 #define S13 17
00181 #define S14 22
00182 #define S21 5
00183 #define S22 9
00184 #define S23 14
00185 #define S24 20
00186 #define S31 4
00187 #define S32 11
00188 #define S33 16
00189 #define S34 23
00190 #define S41 6
00191 #define S42 10
00192 #define S43 15
00193 #define S44 21
00194 static void MD5Transform(UInt32*, const unsigned char*);
00195 static void Encode(unsigned char *, UInt32 *, UInt32);
00196 static void Decode(UInt32 *, const unsigned char *, UInt32);
00197 //static void MD5_memcpy(POINTER, POINTER, UInt32);
00198 //static void MD5_memset(POINTER, Int32, UInt32);
00199 static unsigned char PADDING[64] = {
00200    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00201    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00202    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00203 };
00204 /* F, G, H and I are basic MD5 functions.
00205  */
00206 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
00207 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
00208 #define H(x, y, z) ((x) ^ (y) ^ (z))
00209 #define I(x, y, z) ((y) ^ ((x) | (~z)))
00210 /* ROTATE_LEFT rotates x left n bits.
00211  */
00212 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
00213 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
00214 Rotation is separate from addition to prevent recomputation.
00215  */
00216 #define FF(a, b, c, d, x, s, ac) { \
00217  (a) += F ((b), (c), (d)) + (x) + static_cast<UInt32>(ac); \
00218  (a) = ROTATE_LEFT ((a), (s)); \
00219  (a) += (b); \
00220   }
00221 #define GG(a, b, c, d, x, s, ac) { \
00222  (a) += G ((b), (c), (d)) + (x) + static_cast<UInt32>(ac); \
00223  (a) = ROTATE_LEFT ((a), (s)); \
00224  (a) += (b); \
00225   }
00226 #define HH(a, b, c, d, x, s, ac) { \
00227  (a) += H ((b), (c), (d)) + (x) + static_cast<UInt32>(ac); \
00228  (a) = ROTATE_LEFT ((a), (s)); \
00229  (a) += (b); \
00230   }
00231 #define II(a, b, c, d, x, s, ac) { \
00232  (a) += I ((b), (c), (d)) + (x) + static_cast<UInt32>(ac); \
00233  (a) = ROTATE_LEFT ((a), (s)); \
00234  (a) += (b); \
00235   }
00236 /* MD5 initialization. Begins an MD5 operation, writing a new context.
00237  */ // STATIC
00238 void
00239    MD5::MD5Init(MD5_CTX* context)
00240 {
00241    context->count[0] = context->count[1] = 0;
00242    /* Load magic initialization constants.
00243  */
00244    context->state[0] = 0x67452301;
00245    context->state[1] = 0xefcdab89;
00246    context->state[2] = 0x98badcfe;
00247    context->state[3] = 0x10325476;
00248 }
00249 /* MD5 block update operation. Continues an MD5 message-digest
00250   operation, processing another message block, and updating the
00251   context.
00252  */ // STATIC
00253 void
00254    MD5::MD5Update(MD5_CTX* context, const unsigned char* input,
00255    UInt32 inputLen)
00256 {
00257    UInt32 i, index, partLen;
00258    /* Compute number of bytes mod 64 */
00259    index = ((context->count[0] >> 3) & 0x3F);
00260    /* Update number of bits */
00261    if ((context->count[0] += (inputLen << 3)) < (inputLen << 3))
00262    {
00263       context->count[1]++;
00264    }
00265    context->count[1] += (inputLen >> 29);
00266    partLen = 64 - index;
00267    /* Transform as many times as possible.
00268  */
00269    if (inputLen >= partLen)
00270    {
00271       memcpy(static_cast<POINTER>(&context->buffer[index]), 
00272          static_cast<const unsigned char*>(input), partLen);
00273       MD5Transform (context->state, context->buffer);
00274       for (i = partLen; i + 63 < inputLen; i += 64)
00275          MD5Transform (context->state, &input[i]);
00276       index = 0;
00277    }
00278    else
00279       i = 0;
00280    /* Buffer remaining input */
00281    memcpy
00282       (static_cast<POINTER>(&context->buffer[index]), 
00283          static_cast<const unsigned char*>(&input[i]),
00284       inputLen-i);
00285 }
00286 /* MD5 finalization. Ends an MD5 message-digest operation, writing the
00287   the message digest and zeroizing the context.
00288  */ // STATIC
00289 void
00290    MD5::MD5Final (unsigned char* digest, MD5_CTX* context)
00291 {
00292    unsigned char bits[8];
00293    UInt32 index, padLen;
00294    /* Save number of bits */
00295    Encode (bits, context->count, 8);
00296    /* Pad out to 56 mod 64.
00297  */
00298    index = ((context->count[0] >> 3) & 0x3f);
00299    padLen = (index < 56) ? (56 - index) : (120 - index);
00300    MD5Update (context, PADDING, padLen);
00301    /* Append length (before padding) */
00302    MD5Update (context, bits, 8);
00303    /* Store state in digest */
00304    Encode (digest, context->state, 16);
00305    /* Zeroize sensitive information.
00306  */
00307    memset (reinterpret_cast<POINTER>(context), 0, sizeof (*context));
00308 }
00309 /* MD5 basic transformation. Transforms state based on block.
00310  */
00311 static void MD5Transform (UInt32* state, const unsigned char* block)
00312 {
00313    UInt32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
00314    Decode (x, block, 64);
00315    /* Round 1 */
00316    FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
00317    FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
00318    FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
00319    FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
00320    FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
00321    FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
00322    FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
00323    FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
00324    FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
00325    FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
00326    FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
00327    FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
00328    FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
00329    FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
00330    FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
00331    FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
00332    /* Round 2 */
00333    GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
00334    GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
00335    GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
00336    GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
00337    GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
00338    GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
00339    GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
00340    GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
00341    GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
00342    GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
00343    GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
00344    GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
00345    GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
00346    GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
00347    GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
00348    GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
00349    /* Round 3 */
00350    HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
00351    HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
00352    HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
00353    HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
00354    HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
00355    HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
00356    HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
00357    HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
00358    HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
00359    HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
00360    HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
00361    HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
00362    HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
00363    HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
00364    HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
00365    HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
00366    /* Round 4 */
00367    II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
00368    II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
00369    II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
00370    II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
00371    II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
00372    II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
00373    II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
00374    II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
00375    II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
00376    II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
00377    II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
00378    II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
00379    II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
00380    II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
00381    II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
00382    II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
00383    state[0] += a;
00384    state[1] += b;
00385    state[2] += c;
00386    state[3] += d;
00387    /* Zeroize sensitive information. */
00388    memset (reinterpret_cast<POINTER>(x), 0, sizeof (x));
00389 }
00390 /* Encodes input (UInt32) into output (unsigned char). Assumes len is
00391   a multiple of 4.
00392  */
00393 static void Encode (unsigned char* output, UInt32* input, UInt32 len)
00394 {
00395    UInt32 i, j;
00396    for (i = 0, j = 0; j < len; i++, j += 4)
00397    {
00398       output[j] = (input[i] & 0xff);
00399       output[j+1] = ((input[i] >> 8) & 0xff);
00400       output[j+2] = ((input[i] >> 16) & 0xff);
00401       output[j+3] = ((input[i] >> 24) & 0xff);
00402    }
00403 }
00404 /* Decodes input (unsigned char) into output (UInt32). Assumes len is
00405   a multiple of 4.
00406  */
00407 static void Decode (UInt32* output, const unsigned char* input, UInt32 len)
00408 {
00409    UInt32 i, j;
00410    for (i = 0, j = 0; j < len; i++, j += 4)
00411       output[i] = (static_cast<UInt32>(input[j])) | ((static_cast<UInt32>(input[j+1])) << 8) |
00412          ((static_cast<UInt32>(input[j+2])) << 16) | ((static_cast<UInt32>(input[j+3])) << 24);
00413 }
00414 /* Note: Replace "for loop" with standard memcpy if possible.
00415  */
00416 //static void MD5_memcpy (POINTER output, POINTER input, UInt32 len)
00417 //{
00418    //UInt32 i;
00419    //for (i = 0; i < len; i++)
00420    // output[i] = input[i];
00421 //}
00422 /* Note: Replace "for loop" with standard memset if possible. */
00423 //static void MD5_memset (POINTER output, Int32 value, UInt32 len)
00424 //{
00425    //UInt32 i;
00426    //for (i = 0; i < len; i++)
00427    // ((char *)output)[i] = (char)value;
00428 //}
00429 
00430 } // end namespace OW_NAMESPACE
00431 
00432 
00433 #ifdef OW_WIN32
00434 #pragma warning (pop)
00435 #endif
00436 

Generated on Thu Feb 9 08:48:05 2006 for openwbem by  doxygen 1.4.6