C# Code Snippet: Creating an md5 hash string.

While writing some code to cache objects from the web (actually items in an RSS channel) in a local database, I ran into the problem of uniquely identifying items in the database. RSS 0.91 defines an optional “guid” element that uniquely identifies an item, but many sites don’t provide it. There was no “key” that I could use to see if the data was already in the database, so I wanted to generate one using a hashing algorithm.

The .NET framework has GetHashCode() which seems promising, and which every object must support, but it returns an int, and considering the database could potentially have hundreds of thousands of entries in it, multiple objects generating the same hash code would eventually happen. Duplication wouldn’t be a catastrophic problem, but if it happened frequently, it would make the caching less useful.

The framework can generate an MD5 hash of an arbitrary piece of data, which is just what I want - a unique enough hash that it’s very unlikely that two arbitrary pieces of information would generate the same hash. The MD5 algorithm takes as input a message of arbitrary length and produces as output a 128-bit “fingerprint” of the input. The .NET framework glue for taking the 128-bit binary data and turn it into a hex string was a bit of a pain to figure out, so I’m presenting what I wrote here both to provide an example to anyone else with a similar need, and to ask if there’s a better way.

A full description of the MD5 algorithm is available in rfc1321.

using System;
using System.Text;
using System.Security.Cryptography;

// Create an md5 sum string of this string
static public string GetMd5Sum(string str)
{
    // First we need to convert the string into bytes, which
    // means using a text encoder.
    Encoder enc = System.Text.Encoding.Unicode.GetEncoder();

    // Create a buffer large enough to hold the string
    byte[] unicodeText = new byte[str.Length * 2];
    enc.GetBytes(str.ToCharArray(), 0, str.Length, unicodeText, 0, true);

    // Now that we have a byte array we can ask the CSP to hash it
    MD5 md5 = new MD5CryptoServiceProvider();
    byte[] result = md5.ComputeHash(unicodeText);

    // Build the final string by converting each byte
    // into hex and appending it to a StringBuilder
    StringBuilder sb = new StringBuilder();
    for (int i=0;i<result.Length;i++)
    {
        sb.Append(result[i].ToString("X2"));
    }

    // And return it
    return sb.ToString();
}

Thanks to Johannes Hiemer for pointing out a bug in my initial version.

11 Responses to “C# Code Snippet: Creating an md5 hash string.”

  1. Matt Says:

    Great. that rocks, and its hell fast too: 1000 iterations in under 1/2 a second on my laptop…

  2. Nick Says:

    Instead of using a StringBuilder, use Convert.ToBase64String(result). That will do 6 bits per character instead of 4 (so the output string will be shorter).

    You should also use MD5CryptoServiceProvider.Create() rather than ‘new’ because it is faster. Or just MD5.Create() for short.

    byte[] input = Encoding.UTF8.GetBytes(inputString);
    byte[] output = MD5.Create().ComputeHash(input);
    return Convert.ToBase64String(output);

    Something like this would be sufficient (and faster). If you want to support Unicode, just type Unicode instead of UTF8.

    If you want even faster, keep the MD5 in a static variable so that it only has to be created once.

  3. Tomas Says:

    You really should’nt use Convert.ToBase64String() because that returns a non-hex decimal value.
    A true hex is Base16.

    If, like in my case, you want to have a Windows App working in conjunction with a WebApp this would’nt work.
    In ASP.NET you use:

    System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(string,”MD5″)

    which returns a correct MD5 hash with Base16 hex.
    But that function is not available in a Windows App.

    This function gets a little closer, but still has some flaws:

    public string GenPwdHash(string src)
    {
    string str = “”;
    byte[] btySrc = ASCIIEncoding.ASCII.GetBytes(src);
    MD5CryptoServiceProvider objMD5 = new MD5CryptoServiceProvider();
    byte[] btyRes = objMD5.ComputeHash(btySrc);
    int intTot = (btyRes.Length * 2 + (btyRes.Length / 8));
    StringBuilder strRes = new StringBuilder(intTot);
    int intI;
    for (int intI = 0; intI

  4. Jeremy Says:

    The original code is very useful in that it matches output from MySQL’s MD5 call. If you’re switching from MySQL to C#, or still using MySQL with C# then this original poster’s code is the way to go. However, Nick’s code may be faster; I have not tested it.

  5. Rosy Says:

    i had database which had password coded to MD5 using PHP but now i had to compare that string for login with C# .how can i do that .above method give different MD5 value in C# from PHP MD5 encoded password .

    please give me solution .

  6. vijay Says:

    Hi,
    It is very use ful for me. but how can reform the hashed password.

  7. Damon Carr Says:

    If you were going to declare the MD5 instance as static would’t you need to use some thread sync? Something easy like:

    lock (_staticMD5)
    {
    _staticMD5.Clear();
    result = _staticMD5.ComputeHash(rawText);
    }

    where:

    private static MD5 _staticMD5 = MD5.Create();

    Is the call to .Clear() even necessary?

    I am using this for a screen scrape app to sense changes in external web-pages and unfortunately they put in a date/time, which I have to strip out. I get the data as UTF8. I’m not sure of the benefit of padding for Unicode in my case (although as a general case I can see this is the only option).

    All my ‘Crypto’ code is localized in a class called CryptoServices which is not a static class. This is the only static method. As this is on a web-site I am concerned about threading issues, but the ONLY shared data is the _staticMD5 variable. However, I believe this lock would make it OK…

    Comments?

    Thanks,
    Damon

  8. keith smith Says:

    Encryption is used for scrambling text for later decryption. Hashing is one way, you can’t get the original value out of a hash. For passwords, when you set the password, you hash the password, and store the hash. When a user logs in, hash the typed password, and compare it to the stored hash.

  9. evyatar ben-shitrit Says:

    http://msdn2.microsoft.com/en-us/library/system.security.cryptography.md5(vs.80).aspx

    There was a bug in the initial version?

  10. ÜberUtils - Part 1 : Cryptography - BradVin's .Net Blog Says:

    [...] here. I’ve had a scenario in the past when I needed to compute a MD5 hash of a string. I also found this blog post on the subject and decided I can now use extension methods to add this functionality to every [...]

  11. Chris Says:

    Thanks for the snippet, worked instantly and greatly helped me out!

Leave a Reply