System.Guid.NewGuid()有多随机?

55

我知道这可能听起来像是一个无意义的问题,但请听我解释...

我想知道GUID是否可以被信任生成一个100%独一无二且不可能被预测的值。

我正在为一个网站制作自己的登录系统,想知道GUID是否足够安全用于会话cookie。

如果提供关于GUID生成方式的背景信息将有助于评估答案。

感谢提供重复问题链接,然而,我的问题特定于.Net框架。


重复:https://dev59.com/jHVC5IYBdhLWcg3wykUt - John Sheehan
还有一个问题:https://dev59.com/enVD5IYBdhLWcg3wQJOT - John Sheehan
还有第三个:http://stackoverflow.com/questions/462219/xkcd-random-number(好吧,不是真的,但有点相关) - Shog9
顺便说一句:这不是你问的问题,但我怀疑这是你想问的问题:https://dev59.com/snVD5IYBdhLWcg3wTZxm - Shog9
据我所知,这个问题的所有回复和评论都没有真正回答它。幸运的是,另一个问题https://dev59.com/PHE85IYBdhLWcg3wwWet有答案(基本上它不是加密随机的)。 - Andy
显示剩余3条评论
8个回答

30

1
@John:这是.NET中使用的算法吗? - GateKiller
5
总之,它们并不是非常随机的。也就是说,来自同一服务器的连续GUID会有很多相似之处。 - Michael Haren
11
这不是.NET中使用的算法。这描述的是版本1。.NET使用版本4(有关版本4的简要说明,请参见http://en.wikipedia.org/wiki/Universally_Unique_Identifier#Version_4_.28random.29)。 - awe
12
尽管这理论上回答了问题,但最好在此处包含答案的关键部分,并提供链接作为参考。 - SuperBiasedMan
3
这篇文章到底回答了什么问题?它对GUID生成的随机性和可预测性有什么说法?我认为http://blogs.msdn.com/b/oldnewthing/archive/2012/05/23/10309199.aspx回答得更好,即GUID生成是几乎唯一的,但不是随机的,也是可预测的。 - Bochu
显示剩余6条评论

13

没有固定长度的值可以保证100%独一无二(只要调用足够次数,忽略宇宙的结束;-p)-但它可能非常,非常,非常不可能重复。


1
根据https://msdn.microsoft.com/en-us/library/bb417a2c-7a58-404f-84dd-6b494ecf0d13#id11所述,自1999年的Windows 2000以来,“Windows中构建的所有版本4 GUID的随机位都是通过Windows CryptGenRandom加密API或等效源获得的,这与生成加密密钥使用的源相同”。因此,我认为它们在密码学上是安全的——至少提供了122位熵。 - Jordan Rieger

5

我无法确定连续数字的可预测性,但它将是唯一的。不过,我认为最好使用System.Security.Cryptography中的随机数生成器。将一个随机数与一个单调递增的值(时间)绑定以生成您的唯一密钥,这样您就可以确保它是唯一且不可预测的。


4
我想知道是否可以信任GUID生成一个值,这个值在所有情况下都是独一无二的且不可能被预测。我正在为网站滚动我的登录系统,想知道GUID是否足够安全用于会话Cookie。
简短回答:根本不行。需要注意的是,唯一和随机完全不同。如果您有一个通用计数器(就像在熟食店取号码),这些数字是唯一的,但完全可预测。
正如Bochu在上面指出的那样,Raymond在这里的帖子中谈到了这个问题:https://devblogs.microsoft.com/oldnewthing/20120523-00/?p=7553 “GUID生成算法旨在实现唯一性,并非旨在实现随机性或不可预测性。事实上,如果您查看早期的讨论,您会发现所谓的Algorithm 1是非随机的并且完全可预测的......即使是第4版GUID算法(基本上是“将版本设置为4并使用随机或伪随机数填充其他所有内容”)也不能保证不可预测,因为该算法未指定随机数生成器的质量。”
对于安全的随机数,您需要一个加密安全的随机数生成器。
顺便说一句,“滚动我的登录系统”是一个安全警告标志 - 如果我没有指出这一点,那就不负责任了。

4
System.Guid.NewGuid()的文档并不保证随机性,所以虽然当前实现基于随机数生成器(版本4的算法,在版本1使用MAC地址后出现了隐私问题,其他系统如Apple的OS X仍使用版本1的算法)。因此,尽管System.Guid.NewGuid()生成唯一值的概率非常高,但不能对其可预测性做出任何假设,因为文档没有指定。

仅供参考:版本4的构建方式简介: http://en.wikipedia.org/wiki/Universally_Unique_Identifier#Version_4_.28random.29 - awe

3
我不太了解.NET,但UUID算法定义得相当精确。
编辑:如果您查看适当的位(请参见维基百科条目),那应该可以解释使用哪个版本的UUID。
编辑2:您使用“安全”一词是一个警示信号,这告诉我您最好使用一个明确定义的加密方法。例如,在服务器上生成会话ID时,为什么不简单地将以下适当子集的串联应用MD5哈希:{客户机IP地址,顺序递增的计数器,您选择的固定秘密常量,您选择的随机数生成器的输出等}?

在 .Net 中,System.Guid 是一个128位的UUID。 - Tracker1
在您提供的维基百科文章中,.Net 中使用版本 4 的是 System.Guid。 - awe

3

假设System.Guid.NewGuid使用CoCreateGuid,那么它根本不是随机的。历史上,创建guid的算法是将网络适配器的MAC地址与一些其他东西(如时间)结合起来。我不确定算法是否已更改。虽然它肯定不是随机的,但保证是唯一的。


它已经改变了:http://www.tech-archive.net/Archive/VC/microsoft.public.vc.mfc/2008-09/msg00302.html - Ohad Schneider

1

GUID(全局唯一标识符)在所有方面都是独一无二的。曾经有一些GUID0生成例程会生成连续的GUID,但这些问题出现在Win98上,并由Microsoft进行了热修复。

您应该能够信任生成的GUID是唯一的,永远不会重复或重新生成。

(编辑:话虽如此,我们都知道,如果字符串长度固定,那么字母数字字符的排列组合数是固定的。但在GUID的情况下,排列组合数是经济实惠的*。)

(*该死,那个XKCD在哪里提出“天文数字”不够大的问题?)


“27”和“27”怎么样?即使它们被合理地生成,也不能真正保证它们是唯一的 - 只是重复出现的可能性非常小而已。 - Marc Gravell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接