Code

Rewrote code to get rid of 32/64 bit problems, and to make is more stream-like. A...
authorishmal <ishmal@users.sourceforge.net>
Sun, 13 Apr 2008 06:32:58 +0000 (06:32 +0000)
committerishmal <ishmal@users.sourceforge.net>
Sun, 13 Apr 2008 06:32:58 +0000 (06:32 +0000)
src/pedro/pedroutil.cpp
src/pedro/pedroutil.h

index d1fb15edca86cfc4ad0b54a4244e458e76578960..c9dbeaa812587440ae62409a9aa13a2425802649 100644 (file)
@@ -480,164 +480,140 @@ DOMString Md5::hashHex(unsigned char *dataIn, unsigned long len)
     return ret;
 }
 
-
-
-/*
- * Note: this code is harmless on little-endian machines.
- */
-/*
-static void byteReverse(unsigned char *buf, unsigned long longs)
+DOMString Md5::hashHex(const DOMString &str)
 {
-    do
-        {
-        unsigned long t = (unsigned long)
-            ((unsigned) buf[3] << 8 | buf[2]) << 16 |
-            ((unsigned) buf[1] << 8 | buf[0]);
-        *(unsigned long *) buf = t;
-        buf += 4;
-        } while (--longs);
-}
-*/
-
-static void md5_memcpy(void *dest, void *src, int n)
-{
-    unsigned char *s1 = (unsigned char *)dest;
-    unsigned char *s2 = (unsigned char *)src;
-    while (n--)
-        *s1++ = *s2++;
+    Md5 md5;
+    md5.append(str);
+    DOMString ret = md5.finishHex();
+    return ret;
 }
 
-static void md5_memset(void *dest, char v, int n)
-{
-    unsigned char *s = (unsigned char *)dest;
-    while (n--)
-        *s++ = v;
-}
 
 /**
  * Initialize MD5 polynomials and storage
  */
 void Md5::init()
 {
-    buf[0]  = 0x67452301;
-    buf[1]  = 0xefcdab89;
-    buf[2]  = 0x98badcfe;
-    buf[3]  = 0x10325476;
+    hashBuf[0]  = 0x67452301;
+    hashBuf[1]  = 0xefcdab89;
+    hashBuf[2]  = 0x98badcfe;
+    hashBuf[3]  = 0x10325476;
 
-    bits[0] = 0;
-    bits[1] = 0;
+    nrBytesHi = 0;
+    nrBytesLo = 0;
+    byteNr    = 0;
+    longNr    = 0;
 }
 
-/*
- * Update context to reflect the concatenation of another buffer full
- * of bytes.
- */
-void Md5::append(unsigned char *source, unsigned long len)
-{
 
-    // Update bitcount
-    unsigned long t = bits[0];
-    if ((bits[0] = t + ((unsigned long) len << 3)) < t)
-           bits[1]++;// Carry from low to high
-    bits[1] += len >> 29;
 
-       //Bytes already in shsInfo->data
-    t = (t >> 3) & 0x3f;
 
-
-    // Handle any leading odd-sized chunks
-    if (t)
+/*
+ * Update with one character
+ */
+void Md5::append(unsigned char ch)
+{
+    if (nrBytesLo == 0xffffffff)
         {
-        unsigned char *p = (unsigned char *) in + t;
-        t = 64 - t;
-        if (len < t)
-            {
-            md5_memcpy(p, source, len);
-            return;
-            }
-        md5_memcpy(p, source, t);
-        //byteReverse(in, 16);
-        transform(buf, (unsigned long *) in);
-        source += t;
-        len    -= t;
+        nrBytesLo = 0;
+        nrBytesHi++;
         }
+    else
+        nrBytesLo++;
 
-    // Process data in 64-byte chunks
-    while (len >= 64)
+    //pack 64 bytes into 16 longs
+    inb[byteNr++] = (unsigned long)ch;
+    if (byteNr >= 4)
         {
-        md5_memcpy(in, source, 64);
-        //byteReverse(in, 16);
-        transform(buf, (unsigned long *) in);
-        source += 64;
-        len    -= 64;
+        unsigned long val =
+             inb[3] << 24 | inb[2] << 16 | inb[1] << 8 | inb[0];
+        inBuf[longNr++] = val;
+        byteNr = 0;
+        }
+    if (longNr >= 16)
+        {
+        transform();
+        longNr = 0;
         }
-
-    // Handle any remaining bytes of data.
-    md5_memcpy(in, source, len);
 }
 
+
 /*
- * Update context to reflect the concatenation of another string
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
  */
-void Md5::append(const DOMString &str)
+void Md5::append(unsigned char *source, unsigned long len)
 {
-    append((unsigned char *)str.c_str(), str.size());
+    while (len--)
+        append(*source++);
 }
 
+
 /*
- * Update context to reflect the concatenation of a single character
+ * Update context to reflect the concatenation of another string
  */
-void Md5::append(unsigned char ch)
+void Md5::append(const DOMString &str)
 {
-    append(&ch, 1);
+    append((unsigned char *)str.c_str(), str.size());
 }
 
+
 /*
  * Final wrapup - pad to 64-byte boundary with the bit pattern
  * 1 0* (64-bit count of bits processed, MSB-first)
  */
 void Md5::finish(unsigned char *digest)
 {
-    // Compute number of bytes mod 64
-    unsigned int count = (bits[0] >> 3) & 0x3F;
+    //snapshot the bit count now before padding
+    unsigned long nrBitsLo = nrBytesLo << 3;
+    unsigned long nrBitsHi = (nrBytesHi << 3) | ((nrBytesLo >> 29) & 7);
 
-    // Set the first char of padding to 0x80.
-    // This is safe since there is always at least one byte free
-    unsigned char *p = in + count;
-    *p++ = 0x80;
+    //Append terminal char
+    append(0x80);
 
-    // Bytes of padding needed to make 64 bytes
-    count = 64 - 1 - count;
-
-    // Pad out to 56 mod 64
-    if (count < 8)
+    //pad until we have a 56 of 64 bits, allowing for 8 bytes at the end
+    while (true)
         {
-           // Two lots of padding:  Pad the first block to 64 bytes
-           md5_memset(p, 0, count);
-           //byteReverse(in, 16);
-           transform(buf, (unsigned long *) in);
+        int remain = (int)(nrBytesLo & 63);
+        if (remain == 56)
+            break;
+        append(0);
+        }
 
-           // Now fill the next block with 56 bytes
-           md5_memset(in, 0, 56);
+    //##### Append length in bits
+    int shift;
+    shift = 0;
+    for (int i=0 ; i<4 ; i++)
+        {
+        unsigned char ch = (unsigned char)((nrBitsLo>>shift) & 0xff);
+        append(ch);
+        shift += 8;
         }
-    else
+
+    shift = 0;
+    for (int i=0 ; i<4 ; i++)
         {
-        // Pad block to 56 bytes
-        md5_memset(p, 0, count - 8);
+        unsigned char ch = (unsigned char)((nrBitsHi>>shift) & 0xff);
+        append(ch);
+        shift += 8;
         }
-    //byteReverse(in, 14);
 
-    // Append length in bits and transform
-    ((unsigned long *) in)[14] = bits[0];
-    ((unsigned long *) in)[15] = bits[1];
+    //copy out answer
+    int indx = 0;
+    for (int i=0 ; i<4 ; i++)
+        {
+        digest[indx++] = (unsigned char)((hashBuf[i]      ) & 0xff);
+        digest[indx++] = (unsigned char)((hashBuf[i] >>  8) & 0xff);
+        digest[indx++] = (unsigned char)((hashBuf[i] >> 16) & 0xff);
+        digest[indx++] = (unsigned char)((hashBuf[i] >> 24) & 0xff);
+        }
 
-    transform(buf, (unsigned long *) in);
-    //byteReverse((unsigned char *) buf, 4);
-    md5_memcpy(digest, buf, 16);
     init();  // Security!  ;-)
 }
 
-static char *md5hex = "0123456789abcdef";
+
+
+static const char *md5hex = "0123456789abcdef";
 
 DOMString Md5::finishHex()
 {
@@ -674,85 +650,86 @@ DOMString Md5::finishHex()
  * @parm buf points to an array of 4 unsigned longs
  * @parm in points to an array of 16 unsigned longs
  */
-void Md5::transform(unsigned long *buf, unsigned long *in)
-{
-    unsigned long a = buf[0];
-    unsigned long b = buf[1];
-    unsigned long c = buf[2];
-    unsigned long d = buf[3];
-
-    MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478,  7);
-    MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);
-    MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17);
-    MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);
-    MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf,  7);
-    MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);
-    MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17);
-    MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22);
-    MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8,  7);
-    MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);
-    MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
-    MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
-    MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122,  7);
-    MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
-    MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
-    MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
-
-    MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562,  5);
-    MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340,  9);
-    MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
-    MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);
-    MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d,  5);
-    MD5STEP(F2, d, a, b, c, in[10] + 0x02441453,  9);
-    MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
-    MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);
-    MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6,  5);
-    MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6,  9);
-    MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);
-    MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);
-    MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905,  5);
-    MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8,  9);
-    MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);
-    MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
-
-    MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942,  4);
-    MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11);
-    MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
-    MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
-    MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44,  4);
-    MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);
-    MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);
-    MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
-    MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6,  4);
-    MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);
-    MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);
-    MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23);
-    MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039,  4);
-    MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
-    MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
-    MD5STEP(F3, b, c, d, a, in[ 2] + 0xc4ac5665, 23);
-
-    MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244,  6);
-    MD5STEP(F4, d, a, b, c, in[ 7] + 0x432aff97, 10);
-    MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
-    MD5STEP(F4, b, c, d, a, in[ 5] + 0xfc93a039, 21);
-    MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3,  6);
-    MD5STEP(F4, d, a, b, c, in[ 3] + 0x8f0ccc92, 10);
-    MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
-    MD5STEP(F4, b, c, d, a, in[ 1] + 0x85845dd1, 21);
-    MD5STEP(F4, a, b, c, d, in[ 8] + 0x6fa87e4f,  6);
-    MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
-    MD5STEP(F4, c, d, a, b, in[ 6] + 0xa3014314, 15);
-    MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
-    MD5STEP(F4, a, b, c, d, in[ 4] + 0xf7537e82,  6);
-    MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
-    MD5STEP(F4, c, d, a, b, in[ 2] + 0x2ad7d2bb, 15);
-    MD5STEP(F4, b, c, d, a, in[ 9] + 0xeb86d391, 21);
-
-    buf[0] += a;
-    buf[1] += b;
-    buf[2] += c;
-    buf[3] += d;
+void Md5::transform()
+{
+    unsigned long *i = inBuf;
+    unsigned long a  = hashBuf[0];
+    unsigned long b  = hashBuf[1];
+    unsigned long c  = hashBuf[2];
+    unsigned long d  = hashBuf[3];
+
+    MD5STEP(F1, a, b, c, d, i[ 0] + 0xd76aa478,  7);
+    MD5STEP(F1, d, a, b, c, i[ 1] + 0xe8c7b756, 12);
+    MD5STEP(F1, c, d, a, b, i[ 2] + 0x242070db, 17);
+    MD5STEP(F1, b, c, d, a, i[ 3] + 0xc1bdceee, 22);
+    MD5STEP(F1, a, b, c, d, i[ 4] + 0xf57c0faf,  7);
+    MD5STEP(F1, d, a, b, c, i[ 5] + 0x4787c62a, 12);
+    MD5STEP(F1, c, d, a, b, i[ 6] + 0xa8304613, 17);
+    MD5STEP(F1, b, c, d, a, i[ 7] + 0xfd469501, 22);
+    MD5STEP(F1, a, b, c, d, i[ 8] + 0x698098d8,  7);
+    MD5STEP(F1, d, a, b, c, i[ 9] + 0x8b44f7af, 12);
+    MD5STEP(F1, c, d, a, b, i[10] + 0xffff5bb1, 17);
+    MD5STEP(F1, b, c, d, a, i[11] + 0x895cd7be, 22);
+    MD5STEP(F1, a, b, c, d, i[12] + 0x6b901122,  7);
+    MD5STEP(F1, d, a, b, c, i[13] + 0xfd987193, 12);
+    MD5STEP(F1, c, d, a, b, i[14] + 0xa679438e, 17);
+    MD5STEP(F1, b, c, d, a, i[15] + 0x49b40821, 22);
+
+    MD5STEP(F2, a, b, c, d, i[ 1] + 0xf61e2562,  5);
+    MD5STEP(F2, d, a, b, c, i[ 6] + 0xc040b340,  9);
+    MD5STEP(F2, c, d, a, b, i[11] + 0x265e5a51, 14);
+    MD5STEP(F2, b, c, d, a, i[ 0] + 0xe9b6c7aa, 20);
+    MD5STEP(F2, a, b, c, d, i[ 5] + 0xd62f105d,  5);
+    MD5STEP(F2, d, a, b, c, i[10] + 0x02441453,  9);
+    MD5STEP(F2, c, d, a, b, i[15] + 0xd8a1e681, 14);
+    MD5STEP(F2, b, c, d, a, i[ 4] + 0xe7d3fbc8, 20);
+    MD5STEP(F2, a, b, c, d, i[ 9] + 0x21e1cde6,  5);
+    MD5STEP(F2, d, a, b, c, i[14] + 0xc33707d6,  9);
+    MD5STEP(F2, c, d, a, b, i[ 3] + 0xf4d50d87, 14);
+    MD5STEP(F2, b, c, d, a, i[ 8] + 0x455a14ed, 20);
+    MD5STEP(F2, a, b, c, d, i[13] + 0xa9e3e905,  5);
+    MD5STEP(F2, d, a, b, c, i[ 2] + 0xfcefa3f8,  9);
+    MD5STEP(F2, c, d, a, b, i[ 7] + 0x676f02d9, 14);
+    MD5STEP(F2, b, c, d, a, i[12] + 0x8d2a4c8a, 20);
+
+    MD5STEP(F3, a, b, c, d, i[ 5] + 0xfffa3942,  4);
+    MD5STEP(F3, d, a, b, c, i[ 8] + 0x8771f681, 11);
+    MD5STEP(F3, c, d, a, b, i[11] + 0x6d9d6122, 16);
+    MD5STEP(F3, b, c, d, a, i[14] + 0xfde5380c, 23);
+    MD5STEP(F3, a, b, c, d, i[ 1] + 0xa4beea44,  4);
+    MD5STEP(F3, d, a, b, c, i[ 4] + 0x4bdecfa9, 11);
+    MD5STEP(F3, c, d, a, b, i[ 7] + 0xf6bb4b60, 16);
+    MD5STEP(F3, b, c, d, a, i[10] + 0xbebfbc70, 23);
+    MD5STEP(F3, a, b, c, d, i[13] + 0x289b7ec6,  4);
+    MD5STEP(F3, d, a, b, c, i[ 0] + 0xeaa127fa, 11);
+    MD5STEP(F3, c, d, a, b, i[ 3] + 0xd4ef3085, 16);
+    MD5STEP(F3, b, c, d, a, i[ 6] + 0x04881d05, 23);
+    MD5STEP(F3, a, b, c, d, i[ 9] + 0xd9d4d039,  4);
+    MD5STEP(F3, d, a, b, c, i[12] + 0xe6db99e5, 11);
+    MD5STEP(F3, c, d, a, b, i[15] + 0x1fa27cf8, 16);
+    MD5STEP(F3, b, c, d, a, i[ 2] + 0xc4ac5665, 23);
+
+    MD5STEP(F4, a, b, c, d, i[ 0] + 0xf4292244,  6);
+    MD5STEP(F4, d, a, b, c, i[ 7] + 0x432aff97, 10);
+    MD5STEP(F4, c, d, a, b, i[14] + 0xab9423a7, 15);
+    MD5STEP(F4, b, c, d, a, i[ 5] + 0xfc93a039, 21);
+    MD5STEP(F4, a, b, c, d, i[12] + 0x655b59c3,  6);
+    MD5STEP(F4, d, a, b, c, i[ 3] + 0x8f0ccc92, 10);
+    MD5STEP(F4, c, d, a, b, i[10] + 0xffeff47d, 15);
+    MD5STEP(F4, b, c, d, a, i[ 1] + 0x85845dd1, 21);
+    MD5STEP(F4, a, b, c, d, i[ 8] + 0x6fa87e4f,  6);
+    MD5STEP(F4, d, a, b, c, i[15] + 0xfe2ce6e0, 10);
+    MD5STEP(F4, c, d, a, b, i[ 6] + 0xa3014314, 15);
+    MD5STEP(F4, b, c, d, a, i[13] + 0x4e0811a1, 21);
+    MD5STEP(F4, a, b, c, d, i[ 4] + 0xf7537e82,  6);
+    MD5STEP(F4, d, a, b, c, i[11] + 0xbd3af235, 10);
+    MD5STEP(F4, c, d, a, b, i[ 2] + 0x2ad7d2bb, 15);
+    MD5STEP(F4, b, c, d, a, i[ 9] + 0xeb86d391, 21);
+
+    hashBuf[0] += a;
+    hashBuf[1] += b;
+    hashBuf[2] += c;
+    hashBuf[3] += d;
 }
 
 
@@ -761,9 +738,6 @@ void Md5::transform(unsigned long *buf, unsigned long *in)
 
 
 
-
-
-
 //########################################################################
 //########################################################################
 //### T H R E A D
index aba9e47154335ab0ad4aea298d96541c6ee3428c..d4577a5a4a5ebbc7edd3916c900a14b99123edaa 100644 (file)
@@ -227,21 +227,27 @@ private:
 //########################################################################
 //########################################################################
 
+
 /**
+ * This is a utility version of a simple MD5 hash algorithm.  This is
+ * neither efficient nor fast.  It is intended to be a small simple utility
+ * for hashing small amounts of data in a non-time-critical place.
  *
+ * Note that this is a rewrite whose purpose is to remove any
+ * machine dependencies.
  */
 class Md5
 {
 public:
 
     /**
-     *
+     * Constructor
      */
     Md5()
         { init(); }
 
     /**
-     *
+     * Destructor
      */
     virtual ~Md5()
         {}
@@ -253,25 +259,35 @@ public:
     static void hash(unsigned char *dataIn,
                      unsigned long len, unsigned char *digest);
 
+    /**
+     * Static convenience method.
+     * Hash a byte array of a given length
+     */
     static DOMString hashHex(unsigned char *dataIn, unsigned long len);
 
+    /**
+     * Static convenience method.
+     * Hash a String
+     */
+    static DOMString hashHex(const DOMString &str);
+
     /**
      *  Initialize the context (also zeroizes contents)
      */
     virtual void init();
 
-    /**
-     *
+    /*
+     * Update with one character
      */
-    virtual void append(unsigned char dataIn);
+    virtual void append(unsigned char ch);
 
     /**
-     *
+     * Update with a byte buffer of a given length
      */
     virtual void append(unsigned char *dataIn, unsigned long len);
 
     /**
-     *
+     * Update with a string
      */
     virtual void append(const DOMString &str);
 
@@ -289,15 +305,18 @@ public:
 
 private:
 
-    void transform(unsigned long *buf, unsigned long *in);
-
-    unsigned long buf[4];
-    unsigned long bits[2];
-    unsigned char in[64];
+    void transform();
 
-};
+    unsigned long hashBuf[4];
+    unsigned long inBuf[16];
+    unsigned long nrBytesHi;
+    unsigned long nrBytesLo;
 
+    unsigned long inb[4];  // Buffer for input bytes as longs
+    int           byteNr;  // which byte in long
+    int           longNr;  // which long in 8 long segment
 
+};