View Single Post
Old Aug 2nd, 2006, 5:01 PM   #1
grimpirate
King of Portal
 
grimpirate's Avatar
 
Join Date: Sep 2005
Posts: 439
Rep Power: 4 grimpirate is on a distinguished road
Send a message via Yahoo to grimpirate
Exclamation Trouble with an MD5 implementation

Well I recently made a small md5 hash calculator program and posted it on the finished projects section. However, upon reading some replies Sane said that perhaps I should try implementing it myself, and so I did. However, I'm unsure why my implementation isn't working. Here's the code, it's two java classes, a driver called MD5Test and the MD5 class:

MD5.java
public class MD5
{
	private static final int[] T = new int[64];

	public MD5()
	{
		int i = 0;
		T[i++] = 0xd76aa478;
		T[i++] = 0xe8c7b756;
		T[i++] = 0x242070db;
		T[i++] = 0xc1bdceee;
		T[i++] = 0xf57c0faf;
		T[i++] = 0x4787c62a;
		T[i++] = 0xa8304613;
		T[i++] = 0xfd469501;
		T[i++] = 0x698098d8;
		T[i++] = 0x8b44f7af;
		T[i++] = 0xffff5bb1;
		T[i++] = 0x895cd7be;
		T[i++] = 0x6b901122;
		T[i++] = 0xfd987193;
		T[i++] = 0xa679438e;
		T[i++] = 0x49b40821;
		T[i++] = 0xf61e2562;
		T[i++] = 0xc040b340;
		T[i++] = 0x265e5a51;
		T[i++] = 0xe9b6c7aa;
		T[i++] = 0xd62f105d;
		T[i++] = 0x2441453;
		T[i++] = 0xd8a1e681;
		T[i++] = 0xe7d3fbc8;
		T[i++] = 0x21e1cde6;
		T[i++] = 0xc33707d6;
		T[i++] = 0xf4d50d87;
		T[i++] = 0x455a14ed;
		T[i++] = 0xa9e3e905;
		T[i++] = 0xfcefa3f8;
		T[i++] = 0x676f02d9;
		T[i++] = 0x8d2a4c8a;
		T[i++] = 0xfffa3942;
		T[i++] = 0x8771f681;
		T[i++] = 0x6d9d6122;
		T[i++] = 0xfde5380c;
		T[i++] = 0xa4beea44;
		T[i++] = 0x4bdecfa9;
		T[i++] = 0xf6bb4b60;
		T[i++] = 0xbebfbc70;
		T[i++] = 0x289b7ec6;
		T[i++] = 0xeaa127fa;
		T[i++] = 0xd4ef3085;
		T[i++] = 0x4881d05;
		T[i++] = 0xd9d4d039;
		T[i++] = 0xe6db99e5;
		T[i++] = 0x1fa27cf8;
		T[i++] = 0xc4ac5665;
		T[i++] = 0xf4292244;
		T[i++] = 0x432aff97;
		T[i++] = 0xab9423a7;
		T[i++] = 0xfc93a039;
		T[i++] = 0x655b59c3;
		T[i++] = 0x8f0ccc92;
		T[i++] = 0xffeff47d;
		T[i++] = 0x85845dd1;
		T[i++] = 0x6fa87e4f;
		T[i++] = 0xfe2ce6e0;
		T[i++] = 0xa3014314;
		T[i++] = 0x4e0811a1;
		T[i++] = 0xf7537e82;
		T[i++] = 0xbd3af235;
		T[i++] = 0x2ad7d2bb;
		T[i++] = 0xeb86d391;
	}

	public String hash()
	{
		int A = 0x67452301;
		int B = 0xefcdab89;
		int C = 0x98badcfe;
		int D = 0x10325476;

		int[] M = new int[16];
		int[] X = new int[16];

		// A message of no length
		// Starts here
		M[0] = 0x80000000;

		for(int i = 1; i < M.length; i++)
		{
			M[i] = 0;
		}
		// Ends here

		for(int i = 0; i < M.length / 16; i++)
		{
			for(int j = 0; j < 16; j++)
			{
				X[j] = M[i * 16 + j];
			}

			int AA = A;
			int BB = B;
			int CC = C;
			int DD = D;

			A = round1(A, B, C, D, X[0], 7, 1 - 1);
			D = round1(D, A, B, C, X[1], 12, 2 - 1);
			C = round1(C, D, A, B, X[2], 17, 3 - 1);
			B = round1(B, C, D, A, X[3], 22, 4 - 1);
			A = round1(A, B, C, D, X[4], 7, 5 - 1);
			D = round1(D, A, B, C, X[5], 12, 6 - 1);
			C = round1(C, D, A, B, X[6], 17, 7 - 1);
			B = round1(B, C, D, A, X[7], 22, 8 - 1);
			A = round1(A, B, C, D, X[8], 7, 9 - 1 );
			D = round1(D, A, B, C, X[9], 12, 10 - 1);
			C = round1(C, D, A, B, X[10], 17, 11 - 1);
			B = round1(B, C, D, A, X[11], 22, 12 - 1);
			A = round1(A, B, C, D, X[12], 7, 13 - 1);
			D = round1(D, A, B, C, X[13], 12, 14 - 1);
			C = round1(C, D, A, B, X[14], 17, 15 - 1);
			B = round1(B, C, D, A, X[15], 22, 16 - 1);
			A = round2(A, B, C, D, X[1], 5, 17 - 1);
			D = round2(D, A, B, C, X[6], 9, 18 - 1);
			C = round2(C, D, A, B, X[11], 14, 19 - 1);
			B = round2(B, C, D, A, X[0], 20, 20 - 1);
			A = round2(A, B, C, D, X[5], 5, 21 - 1);
			D = round2(D, A, B, C, X[10], 9, 22 - 1);
			C = round2(C, D, A, B, X[15], 14, 23 - 1);
			B = round2(B, C, D, A, X[4], 20, 24 - 1);
			A = round2(A, B, C, D, X[9], 5, 25 - 1);
			D = round2(D, A, B, C, X[14], 9, 26 - 1);
			C = round2(C, D, A, B, X[3], 14, 27 - 1);
			B = round2(B, C, D, A, X[8], 20, 28 - 1);
			A = round2(A, B, C, D, X[13], 5, 29 - 1);
			D = round2(D, A, B, C, X[2], 9, 30 - 1);
			C = round2(C, D, A, B, X[7], 14, 31 - 1);
			B = round2(B, C, D, A, X[12], 20, 32 - 1);
			A = round3(A, B, C, D, X[5], 4, 33 - 1);
			D = round3(D, A, B, C, X[8], 11, 34 - 1);
			C = round3(C, D, A, B, X[11], 16, 35 - 1);
			B = round3(B, C, D, A, X[14], 23, 36 - 1);
			A = round3(A, B, C, D, X[1], 4, 37 - 1);
			D = round3(D, A, B, C, X[4], 11, 38 - 1);
			C = round3(C, D, A, B, X[7], 16, 39 - 1);
			B = round3(B, C, D, A, X[10], 23, 40 - 1);
			A = round3(A, B, C, D, X[13], 4, 41 - 1);
			D = round3(D, A, B, C, X[0], 11, 42 - 1);
			C = round3(C, D, A, B, X[3], 16, 43 - 1);
			B = round3(B, C, D, A, X[6], 23, 44 - 1);
			A = round3(A, B, C, D, X[9], 4, 45 - 1);
			D = round3(D, A, B, C, X[12], 11, 46 - 1);
			C = round3(C, D, A, B, X[15], 16, 47 - 1);
			B = round3(B, C, D, A, X[2], 23, 48 - 1);
			A = round4(A, B, C, D, X[0], 6, 49 - 1);
			D = round4(D, A, B, C, X[7], 10, 50 - 1);
			C = round4(C, D, A, B, X[14], 15, 51 - 1);
			B = round4(B, C, D, A, X[5], 21, 52 - 1);
			A = round4(A, B, C, D, X[12], 6, 53 - 1);
			D = round4(D, A, B, C, X[3], 10, 54 - 1);
			C = round4(C, D, A, B, X[10], 15, 55 - 1);
			B = round4(B, C, D, A, X[1], 21, 56 - 1);
			A = round4(A, B, C, D, X[8], 6, 57 - 1);
			D = round4(D, A, B, C, X[15], 10, 58 - 1);
			C = round4(C, D, A, B, X[6], 15, 59 - 1);
			B = round4(B, C, D, A, X[13], 21, 60 - 1);
			A = round4(A, B, C, D, X[4], 6, 61 - 1);
			D = round4(D, A, B, C, X[11], 10, 62 - 1);
			C = round4(C, D, A, B, X[2], 15, 63 - 1);
			B = round4(B, C, D, A, X[9], 21, 64 - 1);

			A += AA;
			B += BB;
			C += CC;
			D += DD;
		}

		return Integer.toHexString(A) + Integer.toHexString(B) + Integer.toHexString(C) + Integer.toHexString(D);
	}

	private int round1(int a, int b, int c, int d, int x, int s, int i)
	{
		return b + lShiftRotate((a + F(b, c, d) + x + T[i]), s);
	}

	private int round2(int a, int b, int c, int d, int x, int s, int i)
	{
		return b + lShiftRotate((a + G(b, c, d) + x + T[i]), s);
	}

	private int round3(int a, int b, int c, int d, int x, int s, int i)
	{
		return b + lShiftRotate((a + H(b, c, d) + x + T[i]), s);
	}

	private int round4(int a, int b, int c, int d, int x, int s, int i)
	{
		return b + lShiftRotate((a + I(b, c, d) + x + T[i]), s);
	}

	private int F(int X, int Y, int Z)
	{
		return X & Y | ~X & Z;
	}

	private int G(int X, int Y, int Z)
	{
		return X & Z | Y & ~Z;
	}

	private int H(int X, int Y, int Z)
	{
		return X ^ Y ^ Z;
	}

	private int I(int X, int Y, int Z)
	{
		return Y ^ (X | ~Z);
	}

	public static int lShiftRotate(int x, int y)
	{
		int mask = 0x80000000;

		for(int i = 0; i < y; i++)
		{
			if((x & mask) == 0)
			{
				x = x << 1;
			}
			else
			{
				x = (x << 1) + 1;
			}
		}

		return x;
	}
}
MD5Test.java
public class MD5Test
{
	public static void main(String[] args)
	{
		MD5 message = new MD5();
		System.out.println(message.hash());
	}
}
Right now the program is only supposed to compute the has/checksum of an empty string/file or whatever. It's the array listed as M, which is originally 0 but as I understand it, if a message has 0 length then it should start with a 1 and follow with 511 0's, which is what I did there to the best of my knowledge. I'm not sure whether or not A, B, C, and D are their proper values as there's some reference to big-endian or little-endian notation and I'm unsure as how to proceed. I copied the values from the RFC reference implementation, as well as the values for T which are supposed to be obtainable by performing a calculation along the lines of Math.floor(Math.abs(Math.sin(i)) * Math.pow(2, 32)) where {i: 1...64}, buuuuuuuuuuut those values weren't anywhere even remotely close when I actually computed it to the hex values given in the reference implementation. If anybody could point out where I have an error, or for that matter a series of cascading errors lol, I'd appreciate it.

P.S. As stated in the RFC the hash for a string of "" should be
MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
__________________
Lo, there do I see my father. 'Lo, there do I see My mother, and my sisters, and my brothers. 'Lo, there do I see The line of my people... Back to the beginning. 'Lo, they do call to me. They bid me take my place among them. In the halls of Valhalla... Where the brave... May live... ...forever.. GrimBB | Mimesis
grimpirate is offline   Reply With Quote