Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

qtmd5.cpp

Go to the documentation of this file.
00001 /* derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm */
00002 #include <qstring.h>
00003 #include "qtmd5.h"
00004 
00005 typedef unsigned char *POINTER;
00006 typedef unsigned short int UINT2;
00007 typedef unsigned long int UINT4;
00008 
00009 typedef struct {
00010     UINT4 state[4];            // state(ABCD)
00011     UINT4 count[2];            // number of bits, modulo 2^64(lsb first)
00012     unsigned char buffer[64];  // input buffer
00013 } MD5_CTX;
00014 
00015 static void MD5Init(MD5_CTX *);
00016 static void MD5Update(MD5_CTX *, unsigned char *, unsigned int);
00017 static void MD5Final(unsigned char [16], MD5_CTX *);
00018 static void MD5Transform(UINT4[4], unsigned char[64]);
00019 static void Encode(unsigned char *, UINT4 *, unsigned int);
00020 static void Decode(UINT4 *, unsigned char *, unsigned int);
00021 static void MD5_memset(POINTER, int, unsigned int);
00022 static void MD5_memcpy(POINTER output,POINTER input,unsigned int len);
00023 
00024 // Constants for MD5Transform routine.
00025 enum {
00026     S11 = 7, S12 = 12, S13 = 17, S14 = 22, S21 = 5, S22 = 9,  S23 = 14, S24 = 20,
00027     S31 = 4, S32 = 11, S33 = 16, S34 = 23, S41 = 6, S42 = 10, S43 = 15, S44 = 21
00028 };
00029 
00030 static unsigned char PADDING[64] = {
00031     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00032     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00033     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00034 };
00035 
00036 // F, G, H and I are basic MD5 functions.
00037 static inline UINT4 F(UINT4 x, UINT4 y, UINT4 z)
00038 {
00039     return(x & y) |((~x) & z);
00040 }
00041 
00042 static inline UINT4 G(UINT4 x, UINT4 y, UINT4 z)
00043 {
00044     return(x & z) |(y &(~z));
00045 }
00046 
00047 static inline UINT4 H(UINT4 x, UINT4 y, UINT4 z)
00048 {
00049     return x ^ y ^ z;
00050 }
00051 
00052 static inline UINT4 I(UINT4 x, UINT4 y, UINT4 z)
00053 {
00054     return y ^(x |(~z));
00055 }
00056 
00057 static inline UINT4 rotateLeft(UINT4 x, UINT4 n)
00058 {
00059     return(x << n) |(x >>(32-(n)));
00060 }
00061 
00062 // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
00063 // Rotation is separate from addition to prevent recomputation.
00064 static inline void FF(UINT4 &a, UINT4 b, UINT4 c, UINT4 d, UINT4 x, UINT4 s, UINT4 ac)
00065 {
00066     a += F(b, c, d) + x + ac;
00067     a = rotateLeft(a, s);
00068     a += b;
00069 }
00070 
00071 static inline void GG(UINT4 &a, UINT4 b, UINT4 c, UINT4 d, UINT4 x, UINT4 s, UINT4 ac)
00072 {
00073     a += G(b, c, d) + x +(UINT4)(ac);
00074     a = rotateLeft(a, s);
00075     a += b;
00076 }
00077 
00078 static inline void HH(UINT4 &a, UINT4 b, UINT4 c, UINT4 d, UINT4 x, UINT4 s, UINT4 ac)
00079 {
00080     a += H(b, c, d) + x +(UINT4)(ac);
00081     a = rotateLeft(a, s);
00082     a += b;
00083 }
00084 
00085 static inline void II(UINT4 &a, UINT4 b, UINT4 c, UINT4 d, UINT4 x, UINT4 s, UINT4 ac)
00086 {
00087     a += I(b, c, d) + x +(UINT4)(ac);
00088     a = rotateLeft(a, s);
00089     a += b;
00090 }
00091 
00092 // MD5 initialization. Begins an MD5 operation, writing a new context.
00093 static void MD5Init(MD5_CTX *context)
00094 {
00095     context->count[0] = context->count[1] = 0;
00096 
00097     // Load magic initialization constants.
00098     context->state[0] = 0x67452301;
00099     context->state[1] = 0xefcdab89;
00100     context->state[2] = 0x98badcfe;
00101     context->state[3] = 0x10325476;
00102 }
00103 
00104 // MD5 block update operation. Continues an MD5 message-digest
00105 // operation, processing another message block, and updating the
00106 // context.
00107 static void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputLen)
00108 {
00109     unsigned int i, index, partLen;
00110     // Compute number of bytes mod 64
00111     index =(unsigned int)((context->count[0] >> 3) & 0x3F);
00112 
00113     // Update number of bits
00114     if ((context->count[0] +=((UINT4)inputLen << 3)) <((UINT4)inputLen << 3))
00115         context->count[1]++;
00116 
00117     context->count[1] +=((UINT4)inputLen >> 29);
00118     partLen = 64 - index;
00119 
00120     // Transform as many times as possible.
00121     if (inputLen >= partLen) {
00122         MD5_memcpy((POINTER)&context->buffer[index],(POINTER)input, partLen);
00123         MD5Transform(context->state, context->buffer);
00124         for (i = partLen; i + 63 < inputLen; i += 64)
00125             MD5Transform(context->state, &input[i]);
00126         index = 0;
00127     } else {
00128         i = 0;
00129     }
00130 
00131     // Buffer remaining input
00132     MD5_memcpy((POINTER)&context->buffer[index],(POINTER)&input[i],
00133                inputLen-i);
00134 }
00135 
00136 // MD5 finalization. Ends an MD5 message-digest operation, writing the
00137 // the message digest and zeroizing the context.
00138 static void MD5Final(unsigned char digest[16], MD5_CTX *context)
00139 {
00140     unsigned char bits[8];
00141     unsigned int index, padLen;
00142 
00143     // Save number of bits
00144     Encode(bits, context->count, 8);
00145 
00146     // Pad out to 56 mod 64.
00147     index =(unsigned int)((context->count[0] >> 3) & 0x3f);
00148     padLen =(index < 56) ?(56 - index) :(120 - index);
00149     MD5Update(context, PADDING, padLen);
00150 
00151     // Append length(before padding)
00152     MD5Update(context, bits, 8);
00153 
00154     // Store state in digest
00155     Encode(digest, context->state, 16);
00156 
00157     // Zeroize sensitive information.
00158     MD5_memset((POINTER)context, 0, sizeof(*context));
00159 }
00160 
00161 // MD5 basic transformation. Transforms state based on block.
00162 static void MD5Transform(UINT4 state[4], unsigned char block[64])
00163 {
00164     UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
00165     Decode(x, block, 64);
00166 
00167     // Round 1
00168     FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
00169     FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
00170     FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
00171     FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
00172     FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
00173     FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
00174     FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
00175     FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
00176     FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
00177     FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
00178     FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
00179     FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
00180     FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
00181     FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
00182     FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
00183     FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
00184 
00185     // Round 2
00186     GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
00187     GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
00188     GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
00189     GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
00190     GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
00191     GG(d, a, b, c, x[10], S22,  0x2441453); /* 22 */
00192     GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
00193     GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
00194     GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
00195     GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
00196     GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
00197     GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
00198     GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
00199     GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
00200     GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
00201     GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
00202 
00203     // Round 3
00204     HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
00205     HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
00206     HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
00207     HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
00208     HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
00209     HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
00210     HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
00211     HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
00212     HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
00213     HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
00214     HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
00215     HH(b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
00216     HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
00217     HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
00218     HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
00219     HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
00220 
00221     // Round 4
00222     II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
00223     II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
00224     II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
00225     II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
00226     II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
00227     II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
00228     II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
00229     II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
00230     II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
00231     II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
00232     II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
00233     II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
00234     II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
00235     II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
00236     II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
00237     II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
00238     state[0] += a;
00239     state[1] += b;
00240     state[2] += c;
00241     state[3] += d;
00242 
00243     // Zeroize sensitive information.
00244     MD5_memset((POINTER)x, 0, sizeof(x));
00245 }
00246 
00247 // Encodes input(UINT4) into output(unsigned char). Assumes len is a
00248 // multiple of 4.
00249 static void Encode(unsigned char *output, UINT4 *input, unsigned int len)
00250 {
00251     unsigned int i, j;
00252     for (i = 0, j = 0; j < len; i++, j += 4) {
00253         output[j] = (unsigned char) (input[i] & 0xff);
00254         output[j+1] = (unsigned char) ((input[i] >> 8) & 0xff);
00255         output[j+2] = (unsigned char) ((input[i] >> 16) & 0xff);
00256         output[j+3] = (unsigned char) ((input[i] >> 24) & 0xff);
00257     }
00258 }
00259 
00260 // Decodes input(unsigned char) into output(UINT4). Assumes len is a
00261 // multiple of 4.
00262 static void Decode(UINT4 *output, unsigned char *input, unsigned int len)
00263 {
00264     unsigned int i, j;
00265     for (i = 0, j = 0; j < len; i++, j += 4)
00266         output[i] =((UINT4)input[j]) |(((UINT4)input[j+1]) << 8) |
00267                   (((UINT4)input[j+2]) << 16) |(((UINT4)input[j+3]) << 24);
00268 }
00269 
00270 // Note: Replace "for loop" with standard memset if possible.
00271 static void MD5_memset(POINTER output, int value, unsigned int len)
00272 {
00273     unsigned int i;
00274     for (i = 0; i < len; i++)
00275         ((char *)output)[i] =(char)value;
00276 }
00277 
00278 // Note: Replace "for loop" with standard memcpy if possible.
00279 static void MD5_memcpy(POINTER output,POINTER input,unsigned int len)
00280 {
00281     unsigned int i;
00282     for (i = 0; i < len; i++)
00283         output[i] = input[i];
00284 }
00285 
00286 void qtMD5(const QByteArray &src, unsigned char *digest)
00287 {
00288     MD5_CTX context;
00289 
00290     MD5Init(&context);
00291     MD5Update(&context, (unsigned char *) src.data(), src.size());
00292     MD5Final(digest, &context);
00293 }
00294 
00295 QString qtMD5(const QByteArray &src)
00296 {
00297     unsigned char digest[16];
00298     qtMD5(src, digest);
00299 
00300     QString output, tmp;
00301     for (int i = 0; i < 16; ++i) 
00302         output += tmp.sprintf("%02x", digest[i]);
00303     return output;
00304 }

Generated on Sat Nov 5 16:18:28 2005 for OPIE by  doxygen 1.4.2