Computing MD5 hashes in C#
I’ve had to create md5 hashes in php before, which can be done by simply using the md5() function. Because I always try to avoid reinventing the wheel, I googled for an example on how to compute these kinds of hashes from c#. It directed me to the Microsoft knowledgebase, article KB307020, but that didn’t work as expected.
That particular article shows how you can compute the MD5 hash of a string and then display the resulting byte array as a new string containing the hexadeximal representation of each byte. Since I needed to compare the hash to a string that was generated by a script on a linux machine, I was especially interested in the ByteArrayToString method from the knowledge base article. I have pasted it below, see if you can spot the error:
static string ByteArrayToString(byte[] arrInput) { int i; StringBuilder sOutput = new StringBuilder(arrInput.Length); for (i=0;i < arrInput.Length -1; i++) { sOutput.Append(arrInput[i].ToString("X2")); } return sOutput.ToString(); }
Yes, indeed… the last byte does not get appended to the resulting string, since the end-loop condition is set to i < arrInput.Length -1. This leaves you with an incorrect string representation of your hash. On top of this, there are two other minor things wrong with this:
- the StringBuilder should be initialized with twice the length of the array, since each byte will take up two chars in the string
- the resulted string is in uppercase while usually hexadecimal representations of MD5 hashes are shown in lower case
The following code does exactly what I wanted: compute an MD5 hash from a string and return the lowercase hexadecimal string representation for it, just like the php md5() function does.
public static string MD5(string str) { byte[] strBytes = ASCIIEncoding.ASCII.GetBytes(str); byte[] resultBytes = MD5CryptoServiceProvider .Create().ComputeHash(strBytes); return ByteArrayToString(resultBytes); } private static string ByteArrayToString(byte[] arrInput) { StringBuilder sOutput = new StringBuilder(arrInput.Length * 2); for (int i = 0; i < arrInput.Length; i++) { sOutput.Append(arrInput[i].ToString("x2")); } return sOutput.ToString(); }
Update: I hadn’t noticed this before, but the ByteArrayToString method is in the KB307020 article twice, the first mention does not contain the Length -1 bug, the second time, in the full code, it is there.
Friday 09 Mar 2007 | Guy Mahieu | c#(t)