65.9K
CodeProject 正在变化。 阅读更多。
Home

在 .Net 中生成唯一密钥

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.74/5 (64投票s)

2006年6月10日

3分钟阅读

viewsIcon

440438

downloadIcon

10202

我需要创建一些唯一的 ID。GUID 很棒,因为它们提供了全局唯一标识符,但它们很大。我的意思是,如果你想在你的应用程序中发布一个唯一的数字,你想把它作为预订号或任何参考号,那么 GUID 显然不是一个解决方案。

引言

我有几个应用程序,我需要在其中创建一些唯一的 ID。GUID 很棒,因为它们提供了全局唯一标识符,但它们很大。我的意思是,如果你想在你的应用程序中发布一个唯一的数字,你想把它作为预订号或任何参考号,那么 GUID 显然不是一个解决方案。因此,我需要一些简单的 ID,它们也是唯一的。例如,当我向我的信用卡处理器发送请求时,会有一个 ID 将我的发票与提供商的交易关联起来。在这里,GUID 不是我想要的。

但是一个相对简单的解决方案是创建顺序 ID,它的大小合适,并且也能保证唯一性。非常好且简单的解决方案!!!不是吗!!我的回答是否定的!!因为它对您的网站来说是一个安全威胁。在 Web 应用程序中,您可以通过仅提供订单参考号来检索您的订单或预订详细信息,您可以轻松地使用暴力破解顺序参考号来检索记录。

在本文中,我将讨论我的一些研究和技术。

使用 DateTime 和 HashCode

使用 DateTime 生成唯一密钥是一种非常常见的做法。我通过在其中引入 HashCode 来重新混合这种方法。比如

DateTime.Now.ToString().GetHashCode().ToString("x"); 

它会给你一些类似 496bffe0 的密钥。乍一看,它似乎满足了唯一密钥的要求,因为它使用当前时间和哈希来生成密钥,但 GetHashCode() 每次都不会产生唯一的代码。尽管 Microsoft 正在使用带有 N 个碰撞解决双哈希函数的双哈希算法,但在我的实验中,我发现了许多碰撞。

使用 GUID 和 HashCode

然后我尝试了


Guid.NewGuid().ToString().GetHashCode().ToString("x");

它给出的密钥类似于 649cf2e3

不知何故,我认为这种字符串表示至少不是唯一的……38 个字符表示为 8 个?好的,32 位,但它仍然是 8 位数字,字符仅限于十六进制值,是的,我的怀疑是正确的,因为我编写了一个程序,生成了 100,000 个密钥,并检查了碰撞,发现了一些重复的密钥。

使用 RNGCryptoServiceProvider 和字符掩码

.net Framework 提供了 RNGCryptoServiceProvider 类,该类使用密码服务提供程序 (CSP) 提供的实现来执行密码随机数生成器 (RNG)。此类通常用于生成随机数。虽然我可以在某种程度上使用这个类来生成唯一的数字,但它也不是无碰撞的。此外,在生成密钥时,我们可以通过使其成为字母数字而不是纯数字来使密钥更加复杂。所以,我将这个类与一些字符掩码一起使用,以生成固定长度的唯一密钥。以下是代码示例

  private string GetUniqueKey()
  {
  int maxSize  = 8 ;
  int minSize = 5 ;
  char[] chars = new char[62];
  string a;
  a = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
  chars = a.ToCharArray();
  int size  = maxSize ;
  byte[] data = new byte[1];
  RNGCryptoServiceProvider  crypto = new RNGCryptoServiceProvider();
  crypto.GetNonZeroBytes(data) ;
  size =  maxSize ;
  data = new byte[size];
  crypto.GetNonZeroBytes(data);
  StringBuilder result = new StringBuilder(size) ;
  foreach(byte b in data )
  { result.Append(chars1)>); }
   return result.ToString();
  }

分析

为了进行实验室测试,我使用上述三种方法创建了 1,000,000 个唯一密钥,并发现了以下结果

生成方法

所用时间

生成的密钥数量

重复密钥的数量

所有固定长度密钥

 

使用 DateTime 和 HashCode

01.56 秒 

10,00,000

500131

 

使用 GUID 和 HashCode

04.45 秒

10,00,000

113

 

使用 RNGCryptoServiceProvider 和字符掩码

 

00.40 秒

10,00,000

0(哇!!)

 


以上分析表明,带有字符掩码的 RNGCrypto 是生成唯一密钥的最佳方法。

注意:以上研究仅用于学习目的。是的,可能还有其他比上面提到的更好的方法。

 

© . All rights reserved.