Getting the same MD5 hash from Native and Managed code

I’m working on a Windows CE project where we’re storing an MD5 hash of a password in a SQL Compact database.  The solution is a mix of both native and managed code, and moth need to have access to both generating and verifying a password hash, so it’s pretty important that we have functions for both that generate the same hash output given the same string input.  Here are the functions I’m using:


Managed


private static string MD5Hash(string str)
{
  MD5 hash = MD5.Create();
  byte[] h = hash.ComputeHash(Encoding.Unicode.GetBytes(str));

  StringBuilder sb = new StringBuilder();
  foreach (byte b in h)
  {
    sb.Append(b.ToString(“x2”));
  }

  return sb.ToString();
}


Native


#include “wincrypt.h”

#define MD5LEN 16

DWORD MD5Hash(TCHAR *input, DWORD inLength, TCHAR *output, DWORD *outLength)
{
  HCRYPTPROV hContext = 0;
  HCRYPTHASH hHash = 0;
  DWORD status = 0;
  TCHAR hexDigits[] = _T(“0123456789abcdef”);
  DWORD hashLen = MD5LEN;
  BYTE hash[MD5LEN];
  TCHAR pair[2];

  if(*outLength < (MD5LEN + 1) * sizeof(TCHAR)) return ERROR_INSUFFICIENT_BUFFER;

  // Get handle to the crypto provider
  if (!CryptAcquireContext(&hContext,
                           NULL,
                           NULL,
                           PROV_RSA_FULL,
                           CRYPT_VERIFYCONTEXT))
  {
    status = GetLastError();
    return status;
  }

  if (!CryptCreateHash(hContext, CALG_MD5, 0, 0, &hHash))
  {
    status = GetLastError();
    CryptReleaseContext(hContext, 0);
    return status;
  }

  if (!CryptHashData(hHash, (BYTE*)input, inLength, 0))
  {
    status = GetLastError();
    CryptReleaseContext(hContext, 0);
    CryptDestroyHash(hHash);
    return status;
  }

  if (CryptGetHashParam(hHash, HP_HASHVAL, hash, &hashLen, 0))
  {
    memset(output, 0, *outLength);
    for (DWORD i = 0; i < hashLen; i++)
    {
      _stprintf(pair, _T(“%c%c”), hexDigits[hash[i] >> 4], hexDigits[hash[i] & 0x0F]);
      _tcsncat(output, pair, 2);
    }

    *outLength = (_tcslen(output) + 1) * sizeof(TCHAR);
  }
  else
  {
    status = GetLastError();
  }

  DEBUGMSG(TRUE, (_T(“MD5 hash of %s: %srn”), input, output));

  CryptDestroyHash(hHash);
  CryptReleaseContext(hContext, 0);

  return status;
}


Both of these will probably work on the desktop as well, but I haven’t actually tested there, so YMMV. 


This is also a great example of why I prefer C# for helping keep things simple.  Generally speaking, fewer lines of code means fewer bugs.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s