我知道这里有很多问题这里以及雷蒙德的优秀问题(像往常一样)帖子。然而,由于创建 GUID 的算法明显发生了变化,我发现很难获得任何最新信息。 MSDN 似乎尝试提供尽可能少的信息。
关于 .NET 4 中如何生成 GUID,我们了解多少?更改了什么?它如何影响安全性(“随机性”)和完整性(“唯一性”)?
我感兴趣的一个具体方面:在 v1 中,似乎不可能在一台计算机上再次生成相同的 GUID,因为涉及时间戳和计数器。在 v4 中,情况不再如此(有人告诉我),因此在单台计算机上获得相同 GUID 的机会......增加了?
I am aware of the multitude of questions here as well as Raymond's excellent (as usual) post. However, since the algorithm to create GUIDs was changed apparently, I found it hard to get my hands on any up-to-date information. The MSDN seems to try and provide as few information as possible.
What is known about how GUIDs are generated in .NET 4? What was changed, and how does it affect the security ("randomness") and integrity ("uniqueness")?
One specific aspect I'm interested in: In v1, it seems to be about impossible to generate the same GUID on a single machine again since there was a timestamp and counter involved. In v4, this is no longer the case (I was told), so the chance to get the same GUID on a single machine ... increased?
发布评论
评论(3)
自 Windows 2000 起,Microsoft 使用版本 4 算法:
您也可以从 .NET 中生成的 GUID 中看到这一点(来自 维基百科):
版本 4 UUID 由 122 个有效位组成,提供 2^122 个不同的值,这是一个非常大的数字。给定一组 H 值,在以 50% 的概率找到第一次随机碰撞之前,我们必须选择的预期值数量可以计算如下(请参阅 维基百科上的生日攻击):
2^122 个不同值的结果(生日范围)约为 2,89e+18。这假设生成的值是随机分布的。显然,如果值分布不均匀,则可以更快地发现随机碰撞。有关更多详细信息,请参阅冲突。
1事实上,Melissa 蠕虫病毒的作者可能是 由于使用版本 1 算法生成的 GUID 而被追踪。
Since Windows 2000 Microsoft uses a version 4 algorithm:
You can see that as well from a GUID generated in .NET (from Wikipedia):
A version 4 UUID consist of 122 significant bits, giving 2^122 distinct values which is a very large number. Given a set of H values, the expected number of values we have to choose before finding the first random collision with a 50% chance can be calculated as follows (see Birthday Attack on Wikipedia):
The result (birthday bound) for 2^122 different values is approximately 2,89e+18. This assumes that the generated values are randomly distributed. Obviously, if the values are distributed unevenly, a random collision can be found faster. For further details also see Collisions.
1As a matter of fact, the author of the Melissa worm could be tracked down due to a GUID generated using a version 1 algorithm.
是的,.NET 4.0 中发生了变化,Guid.NewGuid() 直接调用 CoCreateGuid(),UuidCreate() 的一个小包装。 .NET 的早期版本在 CLR 中调用了辅助函数 GuidNative::CompleteGuid()。其中调用 CoCreateGuid。不知道为什么要进行此更改,听起来只不过是一个小的优化。
无论如何,完全相同的 Windows 函数生成 Guid,算法在过去 10 年中一直相同,它一如既往地可靠。
Yes, there was a change in .NET 4.0, Guid.NewGuid() directly calls CoCreateGuid(), a small wrapper around UuidCreate(). Previous versions of .NET called a helper function in the CLR, GuidNative::CompleteGuid(). Which calls CoCreateGuid. Not sure why this change was made, smells like nothing more than a minor optimization.
At any rate, the exact same Windows function generates the Guid, the algorithm has been the same for the past 10 years, it is as reliable as it ever was.
GUID 生成算法记录在 GUID 本身中,检查变体和(可选)版本。维基百科给出了一个很好的概述:首先,GUID 变体。
变体由第 9 个八位字节的初始位指示,“固定”到
0
、10
、110
或111
>。使用我们可能会得到
“1b579ecd-b72c-4550-b10b-f8dd41699ac1:fam 10110001”
。该系列固定为10
、OSF DCE UUID 或变体 2。该变体定义了一个版本,保存在第 7 个八位位组的更重要的“半字节”中。但是,变体 2 作为 MS 格式,是 little-endian。让我们看一下另一种快速方法:
显示类似的内容
前三个整数组已转置 - 两个表示时间,一个保留;分别为 32、16 和 16 位。最后两组不是,因为最后 8 个八位字节是一个“字符串”:1 个保留八位字节(表示“族”)和 7 个“节点”八位字节。因此,第 7 个版本的八位字节实际上被编码为第 8 个版本(索引 7)。
展开
show
以突出显示版本:我们将得到
"154573de-d420-433b-bb25-aff50590038b: fam 10111011, ver 43"
。所讨论的半字节是4
,因此是版本4:伪随机生成。The GUID generation algorithm is recorded in the GUID itself, checking the variant and (optionally) the version. Wikipedia gives a good rundown: first, GUID Variants.
Variant is indicated by the initial bits of the 9th octet, "pinned" to
0
,10
,110
or111
. Usingwe might get
"1b579ecd-b72c-4550-b10b-f8dd41699ac1: fam 10110001"
. The family is pinned to10
, OSF DCE UUID or variant 2. This variant defines a version, held in the more significant "nibble" of the 7th octet.BUT, variant 2, being an MS format is little-endian. Let's take a look with another quick method:
shows something like
The first three integer groups are transposed—two for time, one reserved; 32, 16 and 16 bits respectively. The last two groups are not, because the last 8 octets are a "string": 1 reserved octet (where the "family" is represented) and 7 "node" octets. So the 7th version octet is actually encoded as the 8th (index 7).
Expanding
show
to highlight the version:We'll get
"154573de-d420-433b-bb25-aff50590038b: fam 10111011, ver 43"
. The nibble in question is the4
, thus version 4: pseudo-random generation.