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:

  1. the StringBuilder should be initialized with twice the length of the array, since each byte will take up two chars in the string
  2. 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.