.net System.Guid.NewGuid()的随机性如何?(拿两个)

.net System.Guid.NewGuid()的随机性如何?(拿两个),.net,random,guid,.net,Random,Guid,在你开始把这个标记为之前,先把我念出来。另一个问题的答案(很可能)不正确 我不知道.NET是如何生成它的GUI的,可能只有微软才知道,但它很有可能只是调用而已。但是,该函数被记录为正在调用。创建UUID的算法如下 长话短说,不管怎样,System.Guid.NewGuid()似乎确实使用了它,因为它生成的所有Guid都符合标准(请参见,我尝试了数百万个Guid,它们都匹配) 换句话说,除了一些已知的位之外,这些guid几乎是随机的 这又提出了一个问题-这种随机性有多大?每个优秀的小程序员都知道,

在你开始把这个标记为之前,先把我念出来。另一个问题的答案(很可能)不正确

我不知道.NET是如何生成它的GUI的,可能只有微软才知道,但它很有可能只是调用而已。但是,该函数被记录为正在调用。创建UUID的算法如下

长话短说,不管怎样,
System.Guid.NewGuid()
似乎确实使用了它,因为它生成的所有Guid都符合标准(请参见,我尝试了数百万个Guid,它们都匹配)

换句话说,除了一些已知的位之外,这些guid几乎是随机的

这又提出了一个问题-这种随机性有多大?每个优秀的小程序员都知道,伪随机数算法的随机性与其种子(又名熵)一样。那么
UuidCreate()
的种子是什么呢?PRNG多久重新播种一次?它的加密能力强吗?或者,如果两台计算机同时意外调用
System.Guid.NewGuid()
,我能期望相同的Guid开始大量涌现吗?如果收集了足够多的顺序生成的guid,那么可以猜测PRNG的状态吗

补充道:为了澄清,我想知道我可以相信它是多么随机,因此,我可以在哪里使用它。因此,让我们在这里建立一个粗略的“随机性”量表:

  • 基本随机性,以当前时间为种子。可用于在纸牌游戏中洗牌,但很少用于其他游戏,因为即使不尝试也很容易发生碰撞
  • 更高级的随机性,不仅使用时间,而且使用其他机器特定的种子因素。可能在系统启动时也只播一次种子。这可用于在数据库中生成ID,因为不太可能重复。尽管如此,这对安全性并不好,因为只要付出足够的努力,就可以预测结果
  • 加密随机性,使用设备噪声或其他高级随机性源作为种子。在每次调用时重新播种,或者至少非常频繁。可用于会话ID,分发给不受信任的方等

  • 我在考虑是否可以将它们用作DB ID,以及算法实现与
    System.Guid.NewGuid()
    (就像NHibernate那样)是否有缺陷的时候提出了这个问题。

    它们是随机的,因此数学上可以证明碰撞不会发生很长时间,因此,您可以假设它们在全球范围内是唯一的。但是,它们在加密方面不强,因为这需要真正的随机性,这在没有专用硬件的计算机中是不可能的。

    产生随机字节但未明确记录以产生加密强随机字节的API不能被信任来产生加密强随机字节

    如果您需要加密的强随机字节,那么您应该使用明确记录的API来生成它们

    public Guid CreateCryptographicallyStrongGuid() {
        var rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
        var data = new byte[16];
        rng.GetBytes(data);
        return new Guid(data);
    }
    
    这些guid只是128位的加密随机性。它们不是结构化的,也不会发生碰撞

    看一些数学知识。使用“一般生日公式”,重新排列

    n=sqrt(-2T*ln(p))


    其中n是所选元素的数量,T是元素的总数(2^128),p是所有n个所选元素将不同的目标概率。如果p=0.99,则得出*n=2.6153204*10^18*。这意味着我们可以在一个系统中每秒生成10亿个真正随机的GUID,持续10亿秒(32年),并且最终有99%以上的几率每个GUID在系统中都是唯一的。

    答案是:你不需要知道这一点。如a的公认答案所述:

    GUID不能保证随机性,它保证唯一性

    中对安全性和随机性作了更有力的说明,其中特别说明了UUID格式:

    不要认为UUID很难猜测;它们不应该被使用 作为安全功能(仅拥有就授予 访问),例如。一个可预测的随机数源将 使局势恶化

    其他任何内容都是实现细节(可能会发生变化)

    Windows详细信息

    通常,人们声称Windows上的行为是有文档记录的,因此可以保证GUI是加密安全的

    现在存档的文件在附录A中提到:

    虽然只有少数版本4的GUI需要 加密随机性,获得Windows中内置的所有版本4 GUI的随机位 通过Windows CryptGenRandom cryptographic API或等效程序,使用相同的源 用于生成加密密钥

    此外,同一文档的第2.5.5节明确提到将“secret GUID”值用作nonce或验证器

    但是:这篇产品行为文档并不是一个通常可以作为产品安全性基础的规范(特别是在.NET环境中)

    事实上,上面的文档描述了特定产品的实现细节。 即使当前的Windows和.NET Framework 4.x实现在Windows上产生真正随机的版本4 UUID值,也不能保证
    System.Guid.NewGuid
    将来或在其他.NET平台(例如Mono、Silverlight、CF、.NET Core等)上会这样做


    例如,早期版本的.NET Core中使用的UUID算法,您可能会得到版本1的UUID(在BSD上)。

    随机的定义与全局唯一的定义没有任何关系

    掷硬币两次,得到HH,HT,TH,TT都是随机的。HH和HT一样随机

    投掷“特殊”硬币
    create table #temp ([id] uniqueidentifier primary key default(newid()), [name] varchar(20))
    insert into #temp (name) values ('apple')
    insert into #temp (name) values ('orange')
    insert into #temp (name) values ('banana')
    select * from #temp
    drop table #temp
    
    id                                   name
    ------------------------------------ --------------------
    911B0CBD-4EED-4EB0-8488-1B2CDD915C02 banana
    56CF3A80-A2DE-4949-9C9B-5F890824EA9C orange
    5990B9FD-143D-41B0-89D1-957B2C57AB94 apple