Thread: MD5 hashing problems =(

  1. #1
    Registered User
    Join Date
    Feb 2005
    Posts
    11

    Angry MD5 hashing problems =(

    Ok, I have this header for MD5 related functions that I'm using for password authentication in something im writing (feel free to scroll through it for now):

    Code:
    #ifndef _MD5_H_
    #define _MD5_H_
    #endif
    
    typedef unsigned long uint32;
    
    struct MD5Context
    {
        uint32 buf[4];
        uint32 bits[2];
        unsigned char in[64];
    };
    
    void MD5Init(struct MD5Context *context);
    void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len);
    void MD5Final(unsigned char digest[16], struct MD5Context *context);
    void MD5Transform(uint32 buf[4], uint32 const in[16]);
    char *MD5str(char *string);
    
    typedef struct MD5Context MD5_CTX;
    
    #ifndef HIGHFIRST
    #define byteReverse(buf, len)
    #else
    void byteReverse (unsigned char *buf, unsigned longs);
    
    #ifndef ASM_MD5
    
    void byteReverse (unsigned char *buf, unsigned longs)
    {
        uint32 t;
        do
        {
            t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
                ((unsigned) buf[1] << 8 | buf[0]);
            *(uint32 *) buf = t;
            buf += 4;
        }
        while (--longs);
    }
    #endif
    #endif
    
    void MD5Init (struct MD5Context *ctx)
    {
        ctx->buf[0] = 0x67452301;
        ctx->buf[1] = 0xefcdab89;
        ctx->buf[2] = 0x98badcfe;
        ctx->buf[3] = 0x10325476;
    
        ctx->bits[0] = 0;
        ctx->bits[1] = 0;
    }
    
    void MD5Update (struct MD5Context *ctx, unsigned char const *buf, unsigned len)
    {
        uint32 t;
    
        t = ctx->bits[0];
        if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
            ctx->bits[1]++;
        ctx->bits[1] += len >> 29;
    
        t = (t >> 3) & 0x3f;
    
        if (t)
        {
            unsigned char *p = (unsigned char *) ctx->in + t;
    
            t = 64 - t;
            if (len < t)
            {
                memcpy (p, buf, len);
                return;
            }
            memcpy (p, buf, t);
            byteReverse (ctx->in, 16);
            MD5Transform (ctx->buf, (uint32 *) ctx->in);
            buf += t;
            len -= t;
        }
    
        while (len >= 64)
        {
            memcpy (ctx->in, buf, 64);
            byteReverse (ctx->in, 16);
            MD5Transform (ctx->buf, (uint32 *) ctx->in);
            buf += 64;
            len -= 64;
        }
        
        memcpy (ctx->in, buf, len);
    }
    
    void MD5Final (unsigned char digest[16], struct MD5Context *ctx)
    {
        unsigned count;
        unsigned char *p;
    
        count = (ctx->bits[0] >> 3) & 0x3F;
    
        p = ctx->in + count;
        *p++ = 0x80;
    
        count = 64 - 1 - count;
    
        if (count < 8)
        {
            memset (p, 0, count);
            byteReverse (ctx->in, 16);
            MD5Transform (ctx->buf, (uint32 *) ctx->in);
    
            memset (ctx->in, 0, 56);
        }
        else
        {
            memset (p, 0, count - 8);
        }
        byteReverse (ctx->in, 14);
    
        ((uint32 *) ctx->in)[14] = ctx->bits[0];
        ((uint32 *) ctx->in)[15] = ctx->bits[1];
    
        MD5Transform (ctx->buf, (uint32 *) ctx->in);
        byteReverse ((unsigned char *) ctx->buf, 4);
        memcpy (digest, ctx->buf, 16);
        memset (ctx, 0, sizeof (ctx));
    }
    
    #ifndef ASM_MD5
    
    #define F1(x, y, z) (z ^ (x & (y ^ z)))
    #define F2(x, y, z) F1(z, x, y)
    #define F3(x, y, z) (x ^ y ^ z)
    #define F4(x, y, z) (y ^ (x | ~z))
    
    #define MD5STEP(f, w, x, y, z, data, s) \
    	( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
    
    void MD5Transform (uint32 buf[4], uint32 const in[16])
    {
        register uint32 a, b, c, d;
    
        a = buf[0];
        b = buf[1];
        c = buf[2];
        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;
    }
    
    char *MD5str(char *string)
    {
        struct MD5Context mdc;
        static unsigned char d[16];
        static char h[36];
        
       	MD5Init(&mdc);
    	MD5Update(&mdc, string, strlen(string));
    	MD5Final(d, &mdc);
    
        sprintf(h, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
        
        return h;
    }
    
    #endif
    and this quick script to compare two hashes and return true if they match:

    Code:
    #include <stdio.h>
    #include "md5.h"
    
    int main(void)
    {
    char hash[35] = "34819d7beeabb926a5c854bc85b3e44";
    
        if(hash == (MD5str("mypassword"))){
            printf("match\n");
        }else{
            printf("no match\n");
        }
    return 0;
    }
    Now, first of all, when calling MD5str() by itself to generate a hash, depending on the plaintext string you're encrypting, sometimes there is a gap in the hash, for example:

    Plaintext: mypassword
    Outputted hash: 34819d7beeabb926 a5c854bc85b3e44
    Correct hash: 34819d7beeabb9260a5c854bc85b3e44

    Plaintext: test123
    Outputted hash: cc 3e747a6afbbcbf8be7668acfebee5
    Correct hash: cc03e747a6afbbcbf8be7668acfebee5

    It seems as if only 0's are being excluded when looking at these examples, however this is not always the case.. it works fine on some strings, generating a complete and correct hash, while it messes up others with a gap as previously demonstrated..

    This is the beginning of the problem though, when using the above code to compare two hashes, I can't for the live of me get it to work properly. It either spits out "match" for _everything_ I throw at it, or "no match" for _everything_, which obviously isn't what I'm going for, heh. I've tweaked the script atleast a couple dozen times now, and tried everything I can think of to get it working properly, only to end up with the same end result...

    My only assumption would be that it's a problem with an MD5 related function other than MD5str() (either MD5Init(), MD5Update(), MD5Final(), or MD5Transform()).. but at this point I'm stuck =(.. and can't get this working properly.. I just need it to compare two (password, in my case) hashes effectively and well, do something, based on the result.. buuut obviously that's not how it's working out .. any help would be *GREATLY* appreciated, thanks in advance!

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > sprintf(h, "%2x%2
    Change all these to be %02x

    20 will still print as "20", but 2 will be printed as "02", not " 2"
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Feb 2005
    Posts
    11
    Thanks, Salem! Well, that clears up the first of my problems, still working out the second heh

  4. #4
    Registered User
    Join Date
    Sep 2004
    Posts
    124
    Code:
    if(hash == (MD5str("mypassword"))){
    strikes me as incorrect. Should it be...

    Code:
     if (strcmp(hash, MD5str("mypassword")) == 0){
    Because you're comparing two strings ... using == compares the pointers, not the strings themselves.

    Edit: just ran that code, and modified the output to display the hash produced as well as the hard-coded one, and got the following:

    no match
    34819d7beeabb926a5c854bc85b3e44
    4eaff9b5a3babdf384246ca0c10a9a05
    Your hard-coded string, aside from being totally different from the hash produced, is only 31 characters in length (you'll need to count the characters as the length mismatch is not visibly obvious due to the proportional font). Or am I missing something?
    Last edited by Driver; 02-28-2005 at 07:23 AM. Reason: Add further information
    I think you can put a signature here.

  5. #5
    Registered User
    Join Date
    Feb 2005
    Posts
    11
    Yeah I did that too (outputting both hashes for manual comparison before comparing them in the code), when trying strcmp() it didn't work for me, but strstr() seems to do the trick.. as far as the hashes, the first hardcoded hash for "mypassword" was missing a "0".. fixed. Thanks for the help.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. No clue how to make a code to solve problems!
    By ctnzn in forum C Programming
    Replies: 8
    Last Post: 10-16-2008, 02:59 AM
  2. File send app - md5 checksum different when load is put on server.
    By (Slith++) in forum Networking/Device Communication
    Replies: 5
    Last Post: 12-31-2007, 01:23 PM
  3. Some questions concerning smp and md5
    By keira in forum C Programming
    Replies: 6
    Last Post: 08-31-2007, 03:03 PM
  4. Creating Linked List Using Hashing and Stack
    By m0ntana in forum C Programming
    Replies: 2
    Last Post: 04-07-2007, 07:11 AM
  5. Hashing, indexing and phonetic normalization for approximate str matching...
    By biterman in forum A Brief History of Cprogramming.com
    Replies: 0
    Last Post: 11-21-2006, 09:42 AM