Christopher M. Jones on 19 Aug 2008 11:06:49 -0700


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

[PLUG] [OT] PHP, binary math, password hashing


I'm trying to port a program from C-something 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/plug-announce
General Discussion  --   http://lists.phillylinux.org/mailman/listinfo/plug