如何种子GUID生成?

时间:2012-11-02 02:03:49

标签: c# .net random guid

在.NET中编写函数以根据种子生成GUID的最简单方法是什么?这样我才能对其唯一性有更大的信心?

string GenerateSeededGuid(int seed) { /* code here */ }

理想情况下,种子将来自CryptGenRandom,它描述了随机数生成如下:

  

此函数生成的数据是加密随机的。它是   比典型随机数生成的数据更随机   生成器,例如C编译器附带的生成器。

     

此函数通常用于生成随机初始化向量   和盐值

     

软件随机数生成器的工作方式基本相同。   它们以随机数开头,称为种子,然后使用   算法根据它生成伪随机比特序列。   这个过程中最困难的部分是获得真正的种子   随机。这通常基于用户输入延迟或抖动   来自一个或多个硬件组件。

     

使用Microsoft CSP, CryptGenRandom 使用相同的随机数   其他安全组件使用的生成器。这允许很多   促进系统范围种子的过程。 CryptoAPI存储了一个   每个用户的中间随机种子。为了形成种子   随机数生成器,一个调用应用程序提供它可能的位   例如,鼠标或键盘定时输入 - 然后   结合存储的种子和各种系统数据和用户   进程ID和线程ID,系统时钟等数据   系统时间,系统计数器,内存状态,可用磁盘集群,   散列用户环境块。这个结果用于播种   伪随机数发生器(PRNG)。 [...]如果应用程序可以访问一个好的随机源,它可以   在调用之前用一些随机数据填充 pbBuffer 缓冲区   的 CryptGenRandom 即可。然后,CSP使用此数据进一步随机化其数据   内部种子。省略初始化的步骤是可以接受的   调用 CryptGenRandom 之前 pbBuffer 缓冲区。

4 个答案:

答案 0 :(得分:13)

您在GenerateSeededGuid方法中真正需要做的就是创建一个128位的随机数并将其转换为Guid。类似的东西:

public Guid GenerateSeededGuid(int seed)
{
  var r = new Random(seed);
  var guid = new byte[16];
  r.NextBytes(guid);

  return new Guid(guid);
}

答案 1 :(得分:13)

tldr; 使用Guid.NewGuid而非尝试发明另一种“更随机”的方法。 (当我想要一个可预测的,可重置的序列时,我能想到从种子创建UUIDvX的唯一原因是。但是,GUID可能也不是最好的方法 2 。)

通过定义为有限范围 - 128位减去 6个版本控制位,所以122 bits of uniqueness for v4 - 只有只有albeit supremely huge number! astronomically big!)“唯一”标识符。

由于Pigeonhole Principle,只有很多鸽笼。如果鸽子最终继续繁殖,每只鸽子的洞数就不够了。由于Birthday Paradox,假设完全随机,两只鸽子将在它们全部填满之前尝试争夺相同的鸽笼。因为没有Master Pigeonhole List 1 这是无法预防的。此外,并非所有动物都是鸽子 3

虽然there are no guarantees as to which GUID generator will be used,.NET使用底层OS调用,这是一个GUIDv4(又名随机UUID )生成器since Windows 2k。据我所知 - 或者非常关心 - 这对于这样的目的而言是随机的。 十多年已经过了很好的审查,而且还没有被替换。


来自维基百科:

  

..只有在接下来的100年中每秒生成10亿UUID后,创建一个重复的概率大约为50%。如果地球上的每个人拥有6亿UUID,那么一次重复的概率约为50%。

1 虽然仍然有一组有限的鸽笼,UUIDv1(又名 MAC UUID ) - 假设独特的时空 - 保证确定性生成唯一编号(在给定计算机上每秒生成一些“相对较小”的理论最大UUID数)。不同的鸽子生活在不同的平行维度 - 真棒!

2 Twitter uses Snowflakes在其自己的分布式唯一ID方案中的并行维度。

3 兔子喜欢住在Burrows,而不是Pigeonholes。 GUID的 use 也充当隐式并行分区。只有当重复的GUID 用于相同的目的时,才会出现与冲突相关的问题。想想有多少重复的自动增量数据库主键!

答案 2 :(得分:0)

    public static Guid SeededGuid(int seed, Random random = null)
    {
        random ??= new Random(seed);
        return Guid.Parse(string.Format("{0:X4}{1:X4}-{2:X4}-{3:X4}-{4:X4}-{5:X4}{6:X4}{7:X4}",
            random.Next(0, 0xffff), random.Next(0, 0xffff),
            random.Next(0, 0xffff),
            random.Next(0, 0xffff) | 0x4000,
            random.Next(0, 0x3fff) | 0x8000,
            random.Next(0, 0xffff), random.Next(0, 0xffff), random.Next(0, 0xffff)));
    }

    //Example 1
    SeededGuid("Test".GetHashCode());
    SeededGuid("Test".GetHashCode());

    //Example 2
    var random = new Random("Test".GetHashCode());
    SeededGuid("Test".GetHashCode(), random);
    SeededGuid("Test".GetHashCode(), random);

此方法基于php v4 uui https://www.php.net/manual/en/function.uniqid.php#94959

答案 3 :(得分:-1)

这有点旧,但是不需要随机生成器。但是,是的,这对于测试目的很有用,但对于一般用途却不是

    public static Guid GenerateSeededGuid<T>(T value)
    {
        byte[] bytes = new byte[16];
        BitConverter.GetBytes(value.GetHashCode()).CopyTo(bytes, 0);
        return new Guid(bytes);
    }