C#: How to generate short MD5 code?

29,580

Solution 1

I like @RichieHindle's answer. However, if you're interested in losing fewer bits of fidelity (and thereby decreasing the risk of collisions), you could take the 128 bit value returned by the MD5 Hash, and encode it using ASCII85 (also known as Base85 encoding), instead of a hexadecimal-based encoding. This will give you the whole hash in 20 bytes (which is more than you wanted, but you could chop 2 bytes off, resulting in much less loss than removing 14 of the 32 bytes you'd get using hex encoding).

Edit: Prashant says 20 characters is close enough, and asked for sample code:

After obtaining the MD5 hash from the MD5.ComputeHash call, you can use Jeff Atwood's ASCII85 encoder:

MD5 m = MD5.Create();
byte[] hash = m.ComputeHash(System.Text.Encoding.ASCII.GetBytes("23"));
Ascii85 encoder = new Ascii85();
encoder.EnforceMarks = false;
string hash85 = encoder.Encode(hash);
Console.Out.WriteLine(hash85);

Yields

2ebDPFFZsD?&,r1fX\$,

so you can just use hash85. The encoder.EnforceMarks makes sure that the encoding doesn't include some typical prefix and suffixes that are associated with ASCII85.

Solution 2

You can just take as much of the MD5 hash as you need, and throw the rest away. All the bits have equal value, so there's no difference between doing that and using some hashing algorithm that natively produces fewer bits.

(If you're doing this for security reasons, remember that fewer bits makes hashes easier to crack, regardless of the algorithm. Even outside of security applications, fewer bits increase the risk of collisions. Also bear in mind that MD5 is relative insecure these days - SHA-1 or SHA-2 are considered more secure.)

Solution 3

MD5 always creates a 128 Bit Hash.

Other smaller Hashtypes (taken from Wikipedia)

Fowler-Noll-Vo hash function (32, 64, 128, 256, 512, or 1024 bits)
Jenkins hash function (32 bits)
MurmurHash (32 or 64 bits)
Pearson hashing (8 bits)

But remember hash collisions

Solution 4

I wouldn't use a hash function if you want to be able to map the result back to its original value without collisions.

If your aim is to turn a small decimal number into a long obfuscated string, just invent some mapping algorithm and encode the result with zBase32 or similar.

public string Obfuscate(long x)
{
    return ToZBase32(BitConverter.GetBytes(x * 63498398L));
}

public long Deobfuscate(string x)
{
    return BitConverter.ToInt64(FromZBase32(x)) / 63498398L;
}

23 gets encoded to "gmuyaiayyyyyy". (63498398 chosen by fair dice roll.)

Solution 5

Use FVNHash - http://www.codeproject.com/KB/security/FnvHash.aspx

You can set the length of your hash, do not use it for security reasons.

Share:
29,580
djmzfKnm
Author by

djmzfKnm

WebDev

Updated on July 09, 2022

Comments

  • djmzfKnm
    djmzfKnm almost 2 years

    When I am encrypting 23 using MD5 encryption I am getting 37693cfc748049e45d87b8c7d8b9aacd this 32-character long string which will always be static for 23.

    I want the same kind of mechanism but that should generate 18 or less (like: 122ff1e4883358b6) characters long string instead 32.

    How I can do that in C#, is there any shorter version of MD5 in c#??

    • Michael Madsen
      Michael Madsen almost 15 years
      MD5 is not encryption, it is a hashing algorithm. There is a big difference between the two; most importantly, hashing cannot be reversed, unlike encryption, because multiple inputs will give the same output.
    • Marc Stober
      Marc Stober almost 15 years
      Hi, Prashant. I see your new comment about using the string in a URL. I can think of a few approaches to make this work again, but maybe we'd be able to give an answer that fits your problem if you expanded on what kinds of inputs you expect to have, exactly why you're making an MD5 hash, and what you want to accomplish with the URL in the end. That way we can short-circuit any objections you may have with new solutions, or maybe even just suggest another approach, like @tvanfosson's Perfect Hash Function idea.
    • djmzfKnm
      djmzfKnm over 14 years
      Hi @Blair: Actually there is nothing special in making URL's like this, I am just inspired by GMAIL message URL's they are making them like: http://mail.google.com/mail/?shva=1#inbox/14461a1185905642 and this is good because on logged in user can view there messages, in the same way in my app also only logged in users are allowed to perform any activity. So instead of giving URL like: http://examle.com/mail/18/ I wantto make them like http://examle.com/mail/14461a1185905642/.
    • djmzfKnm
      djmzfKnm over 14 years
      ... That's why I require some good of encryption function or technique which will not fail in any way and will produce output like google doing, no special chars only numbers and letters.
  • Feidex
    Feidex almost 15 years
    SHA-1 creates a 160 Bit hash.
  • Thomas Owens
    Thomas Owens almost 15 years
    Wouldn't this increase the chances of collision, though? I'm not expert in cryptography, but it just seems like a bad idea to be throwing away portions of a hash and still expect it to maintain its properties.
  • djmzfKnm
    djmzfKnm almost 15 years
    I thought the same, just fetch first 18 chars from MD5 37693cfc748049e45d87b8c7d8b9aacd but can't the fist 18 characters in an MD5 be the same for other string??
  • mmx
    mmx almost 15 years
    Thomas: Well, it will happen in any case. A shorter hash inherently has a higher chance for collisions.
  • Thomas Owens
    Thomas Owens almost 15 years
    Mehrdad: Yes, MD5 has collisions, but I still think it's sufficient for non-critical passwords, file duplicate verification, etc. The only thing you don't want to do is increase the collisions by taking subsets of the output, since that's making a known problem even more visible.
  • tvanfosson
    tvanfosson almost 15 years
    If the values are always smaller than the hash size, you can easily create a hash that won't have collisions. Collisions are only inherent when the size of the data is larger than the size of the hash because then every possible input cannot map one-to-one onto a different hash value.
  • Anwar Chandra
    Anwar Chandra almost 15 years
    because MD5 is one-way hash algorithm, we don't need to consider how to 'unhash' it back. But the problem is: how to make sure that the first 18 character always unique?
  • tvanfosson
    tvanfosson almost 15 years
    Overflow? Might want to convert to a long (or if they're always positive, to unsigned) or you will either lose some range or have some mis-mapped values.
  • Nick Johnson
    Nick Johnson almost 15 years
    You can't make it always unique - it's a hash, by definition it has collisions. The shorter you make it, the more likely a collision is.
  • djmzfKnm
    djmzfKnm almost 15 years
    Ok, this is fine, but the output contains special chars (? , & etc) but I want to pass this has string in URL as parameter so that on the next page I can decrypt it and show the output to the user, something like gmail is doing mail.google.com/mail/?zx=1xjighs8u7ewc&shva=1#inbox/1230e772‌​c539f5e3 . If I'll pass ? or & in url then that will create problem. Can't we remove the special chars from final output to generate output something like "1230f774c459b5f3" (without special characters ??