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 }