00001 
00002 
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 
00032 
00033 #include <MD5Hash.h>
00034 
00035 #include <QtCore/QFile>
00036 #include <QtCore/QByteArray>
00037 #include <QtCore/QBitArray>
00038 
00039 
00040 #define MD5_READ_BUFFER 524288
00041 
00042 
00043 
00044 QString MD5Hash::hashData(const char* bytes, int size)
00045 {
00046         
00047 
00048 
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         
00074 
00075 
00076 
00077 
00078 
00079         if (!file.open(QIODevice::ReadOnly))
00080                 return QString();
00081 
00082         
00083 
00084 
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         
00121         t = ctx->bits[0];
00122         if ((ctx->bits[0] = t + ((unsigned int) length << 3)) < t)
00123                 ctx->bits[1]++; 
00124         ctx->bits[1] += length >> 29;
00125 
00126         t = (t >> 3) & 0x3f; 
00127 
00128         
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         
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         
00157         memcpy(ctx->in, data, length);
00158 }
00159 
00160 QString MD5Hash::finalize(md5Context& ctx)
00161 {
00162         unsigned count;
00163         unsigned char *p;
00164 
00165         
00166         count = (ctx.bits[0] >> 3) & 0x3F;
00167 
00168         
00169         
00170         p = ctx.in + count;
00171         *p++ = 0x80;
00172 
00173         
00174         count = 64 - 1 - count;
00175 
00176         
00177         if (count < 8)
00178         {
00179                 
00180                 memset(p, 0, count);
00181                 md5Transform(ctx.buffer, (unsigned int *) ctx.in);
00182 
00183                 
00184                 memset(ctx.in, 0, 56);
00185         }
00186         else
00187         {
00188                 
00189                 memset(p, 0, count - 8);
00190         }
00191 
00192         
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         
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 
00212 
00213 
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 
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 
00225 
00226 
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 }