views:

2310

answers:

6

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#??

+5  A: 

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

Henrik P. Hessel
SHA-1 creates a 160 Bit hash.
dtb
true.. sorry, corrected it.
Henrik P. Hessel
+5  A: 

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.)

RichieHindle
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.
Thomas Owens
@Thomas: Yes, absolutely. Answer updated.
RichieHindle
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??
Prashant
Thomas: Well, it will happen in any case. A shorter hash inherently has a higher chance for collisions.
Mehrdad Afshari
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.
Thomas Owens
@Prashant: "can't the fist 18 characters in an MD5 be the same for other string?" - yes, that's what we mean by a collision. The shorter the hash, the more chance you have of a collision. But if you're going to generate a short hash, truncating a longer one is a reasonable way to do it - a truncated long hash has no more likelihood of a collision that a hash of the same length which is inherently short.
RichieHindle
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.
tvanfosson
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?
Anwar Chandra
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.
Nick Johnson
+2  A: 

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.

dr. evil
+3  A: 

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.)

dtb
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.
tvanfosson
+11  A: 

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.

Blair Conrad
+1 for introducing me to Base85!
RichieHindle
20 character are fine for me, how to apply your method in in C#? Can you please tell me, or should I ask another separate question for this??
Prashant
Prashant
+1  A: 

this 32-character long string are number from hexadecimal : 0-f you can make it shorter by converting its hexadecimal value to radix of 36 : 0-z

Anwar Chandra