MD5Hash.cpp

Idź do dokumentacji tego pliku.
00001 /****************************************************************************
00002 ** Filename: MD5Hash.cpp
00003 ** Last updated [dd/mm/yyyy]: 01/10/2005
00004 **
00005 ** Computes MD5 hash of a file or buffer [Requires Qt4 - QtCore module].
00006 **
00007 ** The MD5 algorithm was written by Ron Rivest.
00008 ** This class is based on the code written by Colin Plumb in 1993,
00009 ** our understanding is that no copyright is claimed and that this code is in
00010 ** the public domain.
00011 **
00012 ** NO WARRANTY is given for this code.
00013 ** Use it at your own risk.
00014 ** It should produce correct SHA1 digests, but no security-related test has been made.
00015 **
00016 ** Copyright (C) 2005 Angius Fabrizio. All rights reserved.
00017 **
00018 ** This file is part of the OSDaB project (http://osdab.sourceforge.net/).
00019 **
00020 ** This file may be distributed and/or modified under the terms of the
00021 ** GNU General Public License version 2 as published by the Free Software
00022 ** Foundation and appearing in the file LICENSE.GPL included in the
00023 ** packaging of this file.
00024 **
00025 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00026 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00027 **
00028 ** See the file LICENSE.GPL that came with this software distribution or
00029 ** visit http://www.gnu.org/copyleft/gpl.html for GPL licensing information.
00030 **
00031 **********************************************************************/
00032 
00033 #include <MD5Hash.h>
00034 
00035 #include <QtCore/QFile>
00036 #include <QtCore/QByteArray>
00037 #include <QtCore/QBitArray>
00038 
00039 // 512K buffer
00040 #define MD5_READ_BUFFER 524288
00041 
00042 
00043 
00044 QString MD5Hash::hashData(const char* bytes, int size)
00045 {
00046         /*
00047          * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
00048          * initialization constants.
00049          */
00050 
00051         md5Context ctx;
00052 
00053         ctx.buffer[0] = 0x67452301;
00054         ctx.buffer[1] = 0xefcdab89;
00055         ctx.buffer[2] = 0x98badcfe;
00056         ctx.buffer[3] = 0x10325476;
00057 
00058         ctx.bits[0] = 0;
00059         ctx.bits[1] = 0;
00060 
00061         updateHash(&ctx, bytes, size);
00062 
00063         return finalize(ctx);
00064 }
00065 
00066 QString MD5Hash::hashData(const QByteArray& bytes)
00067 {
00068         return hashData(bytes.data(), bytes.size());
00069 }
00070 
00071 QString MD5Hash::hashFile(QFile& file)
00072 {
00073         /* To compute the message digest of a chunk of bytes, declare an
00074          * MD5Context structure, pass it to MD5Init, call MD5Update as
00075          * needed on buffers full of bytes, and then call MD5Final, which
00076          * will fill a supplied 16-byte array with the digest.
00077          */
00078 
00079         if (!file.open(QIODevice::ReadOnly))
00080                 return QString();
00081 
00082         /*
00083          * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
00084          * initialization constants.
00085          */
00086 
00087         md5Context ctx;
00088 
00089         ctx.buffer[0] = 0x67452301;
00090         ctx.buffer[1] = 0xefcdab89;
00091         ctx.buffer[2] = 0x98badcfe;
00092         ctx.buffer[3] = 0x10325476;
00093 
00094         ctx.bits[0] = 0;
00095         ctx.bits[1] = 0;
00096 
00097         long int read;
00098         QByteArray buffer(MD5_READ_BUFFER, 0);
00099         char* data = buffer.data();
00100 
00101         while ( (read = file.read(data, MD5_READ_BUFFER)) > 0 )
00102                 updateHash(&ctx, data, read);
00103 
00104         if (read < 0)
00105                 return QString();
00106 
00107         return finalize(ctx);
00108 }
00109 
00110 QString MD5Hash::hashFile(const QString& filename)
00111 {
00112         QFile file(filename);
00113         return hashFile(file);
00114 }
00115 
00116 void MD5Hash::updateHash(md5Context* ctx, const char* data, long int length)
00117 {
00118         unsigned int t;
00119 
00120         // Update bitcount
00121         t = ctx->bits[0];
00122         if ((ctx->bits[0] = t + ((unsigned int) length << 3)) < t)
00123                 ctx->bits[1]++; // Carry from low to high
00124         ctx->bits[1] += length >> 29;
00125 
00126         t = (t >> 3) & 0x3f; // buffer index
00127 
00128         // Handle any leading odd-sized chunks
00129         if (t)
00130         {
00131                 unsigned char *p = (unsigned char *) ctx->in + t;
00132 
00133                 t = 64 - t;
00134 
00135                 if ((unsigned long int)length < t)
00136                 {
00137                         memcpy(p, data, length);
00138                         return;
00139                 }
00140 
00141                 memcpy(p, data, t);
00142                 md5Transform(ctx->buffer, (unsigned int *) ctx->in);
00143                 data += t;
00144                 length -= t;
00145         }
00146 
00147         // Process data in 64-byte chunks
00148         while (length >= 64)
00149         {
00150                 memcpy(ctx->in, data, 64);
00151                 md5Transform(ctx->buffer, (unsigned int *) ctx->in);
00152                 data += 64;
00153                 length -= 64;
00154         }
00155 
00156         // Handle any remaining bytes of data.
00157         memcpy(ctx->in, data, length);
00158 }
00159 
00160 QString MD5Hash::finalize(md5Context& ctx)
00161 {
00162         unsigned count;
00163         unsigned char *p;
00164 
00165         // Compute number of bytes mod 64
00166         count = (ctx.bits[0] >> 3) & 0x3F;
00167 
00168         // Set the first char of padding to 0x80.
00169         // This is safe since there is always at least one byte free
00170         p = ctx.in + count;
00171         *p++ = 0x80;
00172 
00173         // Bytes of padding needed to make 64 bytes
00174         count = 64 - 1 - count;
00175 
00176         // Pad out to 56 mod 64
00177         if (count < 8)
00178         {
00179                 // Two lots of padding:  Pad the first block to 64 bytes
00180                 memset(p, 0, count);
00181                 md5Transform(ctx.buffer, (unsigned int *) ctx.in);
00182 
00183                 // Now fill the next block with 56 bytes
00184                 memset(ctx.in, 0, 56);
00185         }
00186         else
00187         {
00188                 // Pad block to 56 bytes
00189                 memset(p, 0, count - 8);
00190         }
00191 
00192         // Append length in bits and transform
00193         ((unsigned int *) ctx.in)[14] = ctx.bits[0];
00194         ((unsigned int *) ctx.in)[15] = ctx.bits[1];
00195 
00196         md5Transform(ctx.buffer, (unsigned int *) ctx.in);
00197 
00198         // You may need to wipe variables for security reasons before returning!!!
00199 
00200         QString digest;
00201         digest.sprintf("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
00202                 (ctx.buffer[0])&0xFF, (ctx.buffer[0]>>8)&0xFF, (ctx.buffer[0]>>16)&0xFF, (ctx.buffer[0]>>24)&0xFF,
00203                 (ctx.buffer[1])&0xFF, (ctx.buffer[1]>>8)&0xFF, (ctx.buffer[1]>>16)&0xFF, (ctx.buffer[1]>>24)&0xFF,
00204                 (ctx.buffer[2])&0xFF, (ctx.buffer[2]>>8)&0xFF, (ctx.buffer[2]>>16)&0xFF, (ctx.buffer[2]>>24)&0xFF,
00205                 (ctx.buffer[3])&0xFF, (ctx.buffer[3]>>8)&0xFF, (ctx.buffer[3]>>16)&0xFF, (ctx.buffer[3]>>24)&0xFF
00206                 );
00207         
00208         return digest;
00209 }
00210 
00211 // ************ CORE FUNCTIONS *******************************************
00212 
00213 // #define F1(x, y, z) (x & y | ~x & z)
00214 #define F1(x, y, z) (z ^ (x & (y ^ z)))
00215 #define F2(x, y, z) F1(z, x, y)
00216 #define F3(x, y, z) (x ^ y ^ z)
00217 #define F4(x, y, z) (y ^ (x | ~z))
00218 
00219 // This is the central step in the MD5 algorithm.
00220 #define MD5STEP(f, w, x, y, z, data, s) \
00221         ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
00222 
00223 /*
00224  * The core of the MD5 algorithm, this alters an existing MD5 hash to
00225  * reflect the addition of 16 longwords of new data. MD5Update blocks
00226  * the data and converts bytes into longwords for this routine.
00227  */
00228 void MD5Hash::md5Transform(unsigned int buf[4], unsigned int const in[16])
00229 {
00230         register unsigned int a, b, c, d;
00231 
00232         a = buf[0];
00233         b = buf[1];
00234         c = buf[2];
00235         d = buf[3];
00236 
00237         MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
00238         MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
00239         MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
00240         MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
00241         MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
00242         MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
00243         MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
00244         MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
00245         MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
00246         MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
00247         MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
00248         MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
00249         MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
00250         MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
00251         MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
00252         MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
00253 
00254         MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
00255         MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
00256         MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
00257         MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
00258         MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
00259         MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
00260         MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
00261         MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
00262         MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
00263         MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
00264         MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
00265         MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
00266         MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
00267         MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
00268         MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
00269         MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
00270 
00271         MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
00272         MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
00273         MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
00274         MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
00275         MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
00276         MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
00277         MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
00278         MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
00279         MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
00280         MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
00281         MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
00282         MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
00283         MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
00284         MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
00285         MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
00286         MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
00287 
00288         MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
00289         MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
00290         MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
00291         MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
00292         MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
00293         MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
00294         MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
00295         MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
00296         MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
00297         MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
00298         MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
00299         MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
00300         MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
00301         MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
00302         MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
00303         MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
00304 
00305         buf[0] += a;
00306         buf[1] += b;
00307         buf[2] += c;
00308         buf[3] += d;
00309 }

Wygenerowano Sun Jun 11 12:55:08 2006 dla lanChat programem  doxygen 1.4.6