创建短哈希的最佳方法是什么,类似于小的Url呢?

时间:2009-07-12 20:37:48

标签: c# .net hash short-url

我目前正在使用MD5哈希,但我想找到一些能够创建仅使用[a-z] [A-Z] [0-9]的更短哈希的东西。它只需要大约5-10个字符长。

那里有什么东西已经做到了吗?

更新

我喜欢CRC32哈希。在.NET中有一种干净的计算方法吗?

更新2:

我正在使用Joe提供的链接中的CRC32功能。如何将uInt转换为上面定义的字符?

13 个答案:

答案 0 :(得分:48)

.NET字符串对象具有GetHashCode()函数。它返回一个整数。 将其转换为十六进制,然后转换为长度为8个字符的字符串。

像这样:

string hashCode = String.Format("{0:X}", sourceString.GetHashCode());

更多相关内容:http://msdn.microsoft.com/en-us/library/system.string.gethashcode.aspx

更新:将上述链接中的评论添加到此答案:

  

GetHashCode的行为取决于它的实现   可能会从公共语言运行库的一个版本更改为   另一个。可能发生这种情况的原因是为了提高性能   GetHashCode。

     

如果两个字符串对象相等,则返回GetHashCode方法   相同的价值观但是,没有唯一的哈希码值   每个唯一的字符串值。 不同的字符串可以返回相同的哈希值   代码。

     

来电者须知

     

GetHashCode返回的值是平台相关。它有所不同   .NET Framework的32位和64位版本。

答案 1 :(得分:34)

您的目标是创建URL缩短器还是创建哈希函数?

如果您的目标是创建一个URL缩短器,那么您不需要哈希函数。在这种情况下,您只需要预先生成一系列加密安全随机数,然后将每个要编码的URL分配给序列中的唯一编号。

您可以使用以下代码执行此操作:

using System.Security.Cryptography;

const int numberOfNumbersNeeded = 100;
const int numberOfBytesNeeded = 8;
var randomGen = RandomNumberGenerator.Create();
for (int i = 0; i < numberOfNumbersNeeded; ++i)
{
     var bytes = new Byte[numberOfBytesNeeded];
     randomGen.GetBytes(bytes);
}

使用加密数字生成器会让人们很难预测你生成的字符串,我认为这对你很重要。

然后,您可以使用字母表中的字符将8字节随机数转换为字符串。这基本上是基础计算的变化(从基数256到基数62)。

答案 2 :(得分:16)

我不认为URL缩短服务使用哈希值,我认为它们只有一个运行的字母数字字符串,每个新URL都会增加并存储在数据库中。 如果您确实需要使用哈希函数,请查看此链接:some hash functions 此外,有点offtopic,但取决于你正在做什么这可能是有趣的:Coding Horror article

答案 3 :(得分:11)

只需输入Base36(不区分大小写)或Base64的条目ID。

所以,假设我想使用Base36:

(ID - Base36)
1 - 1
2 - 2
3 - 3
10 - A
11 - B
12 - C
...
10000 - 7PS
22000 - GZ4
34000 - Q8C
...
1000000 - LFLS
2345000 - 1E9EW
6000000 - 3KLMO

如果你使用base64,你可以保持这些更短但后面的URL会区分大小写。你可以看到你仍然得到漂亮,整洁的字母数字键,并保证不会发生碰撞!

答案 4 :(得分:7)

您不能使用 short 哈希,因为您需要从短版本到实际值的一对一映射。对于短哈希,碰撞的可能性太高。正常的,长的哈希,不会是非常人性化的(即使碰撞的可能性很小,那么它仍然不会对我感觉“正确”)。

TinyURL.com seems to use增加的数字,转换为Base 36(0-9,A-Z)。

答案 5 :(得分:3)

您可以通过将它们编码为字母数字来减少MD5哈希中的字符数。每个MD5字符通常表示为十六进制,因此这是16个可能的值。 [a-zA-Z0-9]包含62个可能的值,因此您可以通过获取4个MD5值对每个值进行编码。

编辑:

这是一个函数,它取一个数字(长度为4个十六进制数字)并返回[0-9a-zA-Z]。这应该让您了解如何实现它。请注意,类型可能存在一些问题;我没有测试这段代码。

char num2char( unsigned int x ){
    if( x < 26 ) return (char)('a' + (int)x);
    if( x < 52 ) return (char)('A' + (int)x - 26);
    if( x < 62 ) return (char)('0' + (int)x - 52);
    if( x == 62 ) return '0';
    if( x == 63 ) return '1';
}

答案 6 :(得分:3)

首先,我得到一个随机不同数字的列表。然后我从基本字符串中选择每个char,追加并返回结果。我正在选择5个字符,这将相当于基数62中的6471002个排列。第二部分是检查数据库是否存在,如果没有存储短网址。

 const string BaseUrlChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

 private static string ShortUrl
 {
     get
     {
         const int numberOfCharsToSelect = 5;
         int maxNumber = BaseUrlChars.Length;

         var rnd = new Random();
         var numList = new List<int>();

         for (int i = 0; i < numberOfCharsToSelect; i++)
             numList.Add(rnd.Next(maxNumber));

         return numList.Aggregate(string.Empty, (current, num) => current + BaseUrlChars.Substring(num, 1));
      } 
  }

答案 7 :(得分:2)

您可以使用CRC32,它长8个字节,与MD5类似。将时间戳添加到实际值将支持唯一值。

所以它看起来像http://foo.bar/abcdefg12

答案 8 :(得分:2)

如果您正在寻找一个可以从inters生成微小独特哈希的库,我强烈推荐http://hashids.org/net/。我在许多项目中使用它,它的工作非常棒。您还可以为自定义哈希指定自己的字符集。

答案 9 :(得分:0)

如果您不关心加密强度,任何CRC功能都可以。

Wikipedia列出了一堆不同的哈希函数,包括输出长度。将它们的输出转换为[a-z] [A-Z] [0-9]是微不足道的。

答案 10 :(得分:0)

您可以使用base64而不是十六进制编码md5哈希码,这样您就可以使用字符[a-z] [A-Z] [0-9]来获得更短的网址。

答案 11 :(得分:0)

有一个名为btoa的精彩但古老的程序,它使用大小写字母,数字和两个附加字符将二进制转换为ASCII。还有MIME base64编码;大多数Linux系统可能都有一个名为base64base64encode的程序。任何一个都会给你一个32位CRC的简短可读字符串。

答案 12 :(得分:-1)

您可以使用MD5哈希的第一个字母数字5-10个字符。