Christopher M. Jones on 19 Aug 2008 14:07:01 0700 
Hey. I didn't write it. I'm just responsible for porting it. We were asked to write a web app that allows users to generate authentication keys to use in the application our client sells. When we asked for the algorithm they use for generating keys, this is what we got. Jon Bringhurst wrote: > So, assuming "BYTE"s are octets, it looks like it's getting the md5 of > the string and then splitting it up into 4 parts. Then, it just XORs > each part together, basically introducing a ton of possible collisions > and making the hash very insecure. Why are you doing this again? > > Jon B > > On Tue, Aug 19, 2008 at 2:06 PM, Christopher M. Jones > <cjones@partialflow.com> wrote: >> I'm trying to port a program from Csomething to php that generates a >> hash from password, login, and some other data. I've quoted the relevant >> portions of the source code at the end of this message. >> >> I'm struggling on three counts: >> >> 1. Learning binary math >> 2. Reading the source code >> 3. Replicating it in php >> >> I guess that covers everything ;) >> >> In the source function CalculateFoldedMD5(), it looks like the following >> is happening: >> >> 1. A buffer is created to hold the hash >> 2. The hash is parsed and the bits manipulated >> 3. The bits are recombined >> >> The following vexes me: >> unsigned int a = (bHash[0x0] << 24)  (bHash[0x1] << 16)  (bHash[0x2] >> << 8)  bHash[0x3]; >> >> It looks to me that the construct bHash[0x0] accesses the buffer >> (bHash), which is declared earlier in the function as >> >> BYTE bHash[16] = { 0 } >> >> The buffer length is delared in ComputMD5() as being 16 bits. >> >> So does bHash[0x0] reference the first four bits in the buffer? >> >> If so, then look at this: >> >> unsigned int a = (bHash[0x0] << 24)  (bHash[0x1] << 16)  (bHash[0x2] >> << 8)  bHash[0x3]; >> unsigned int b = (bHash[0x4] << 24)  (bHash[0x5] << 16)  (bHash[0x6] >> << 8)  bHash[0x7]; >> unsigned int c = (bHash[0x8] << 24)  (bHash[0x9] << 16)  (bHash[0xA] >> << 8)  bHash[0xB]; >> unsigned int d = (bHash[0xC] << 24)  (bHash[0xD] << 16)  (bHash[0xE] >> << 8)  bHash[0xF]; >> >> If each hex code represents four bits, then these lines account for 64 >> bits of hash. What do I need to do to get 64 bits of hash? >> >> I did the following: >> >> $hash = base_convert( md5( $word ), 10, 2); >> >> This gives me a string of 1's or 0's, 64 long. The unconverted hash is >> 32 long. So I'm thinking I did the right thing with base_convert(), but >> I really have no idea. I'm stabbing in the dark. >> >> So IF I've parsed the hash properly, my next question is: how to >> replicate the bHash[0x0] structure. I've got no idea, and this is where >> I've reached a dead end. >> >> ANY help would be appreciated. I'm happy to further clarify my questions >> for anyone who wants to take me as a project. >> >> Both source functions are quoted in full below. >> >>  >> >> BOOL ComputeMD5(BYTE *bHash, char *pBuffer, unsigned int uLength) >> { >> HCRYPTPROV hCryptProvider; >> HCRYPTHASH hHash; >> >> BOOL bResult = FALSE; >> >> if (CryptAcquireContext(&hCryptProvider, NULL, NULL, PROV_RSA_FULL, >> CRYPT_VERIFYCONTEXT  CRYPT_MACHINE_KEYSET)) >> { >> if (CryptCreateHash(hCryptProvider, CALG_MD5, 0, 0, &hHash)) >> { >> if (CryptHashData(hHash, (BYTE*)pBuffer, uLength, 0)) >> { >> DWORD dwHashLength = 16; // 128 bit hash >> >> if (CryptGetHashParam(hHash, HP_HASHVAL, bHash, &dwHashLength, 0)) >> bResult = TRUE; >> } >> CryptDestroyHash(hHash); >> } >> CryptReleaseContext(hCryptProvider, 0); >> } >> >> return bResult; >> } >> >> unsigned int ComputeFoldedMD5(CString& strCheck) >> { >> CT2CA strAscii(strCheck); // Convert to ANSI >> BYTE bHash[16] = { 0 }; >> >> if (!ComputeMD5(bHash, strAscii, strlen(strAscii))) >> return 0; >> >> unsigned int a = (bHash[0x0] << 24)  (bHash[0x1] << 16)  (bHash[0x2] >> << 8)  bHash[0x3]; >> unsigned int b = (bHash[0x4] << 24)  (bHash[0x5] << 16)  (bHash[0x6] >> << 8)  bHash[0x7]; >> unsigned int c = (bHash[0x8] << 24)  (bHash[0x9] << 16)  (bHash[0xA] >> << 8)  bHash[0xB]; >> unsigned int d = (bHash[0xC] << 24)  (bHash[0xD] << 16)  (bHash[0xE] >> << 8)  bHash[0xF]; >> >> return a ^ b ^ c ^ d; >> } >> >> >> ___________________________________________________________________________ >> Philadelphia Linux Users Group  http://www.phillylinux.org >> Announcements  http://lists.phillylinux.org/mailman/listinfo/plugannounce >> General Discussion  http://lists.phillylinux.org/mailman/listinfo/plug >> > ___________________________________________________________________________ > Philadelphia Linux Users Group  http://www.phillylinux.org > Announcements  http://lists.phillylinux.org/mailman/listinfo/plugannounce > General Discussion  http://lists.phillylinux.org/mailman/listinfo/plug > ___________________________________________________________________________ Philadelphia Linux Users Group  http://www.phillylinux.org Announcements  http://lists.phillylinux.org/mailman/listinfo/plugannounce General Discussion  http://lists.phillylinux.org/mailman/listinfo/plug

