我想证明一个GUID在一个简单的测试程序中不是唯一的。
我原以为下面的代码会运行几个小时,但它不起作用。我该怎么做呢?
BigInteger begin = new BigInteger((long)0);
BigInteger end = new BigInteger("340282366920938463463374607431768211456",10); //2^128
for(begin; begin<end; begin++)
Console.WriteLine(System.Guid.NewGuid().ToString());
我用的是c#。
假设你有理由相信生成guid的算法并不是生成真正的随机数,而是以周期<< 2^128为周期循环。
例如,RFC4122方法用于派生guid,该guid固定某些位的值。
循环的证明取决于周期的可能大小。
对于小周期,哈希表(GUID) -> GUID与碰撞替换
如果guid不匹配(如果匹配则终止)可能是一种方法。也可以考虑只在随机的一小部分时间内进行替换。
最终,如果两次碰撞之间的最大周期足够大(并且事先不知道),任何方法都只能产生一个概率,即如果碰撞存在的话,就会发现碰撞。
请注意,如果生成guid的方法是基于时钟的(参见RFC),那么可能无法确定是否存在冲突,因为(a)您无法等待足够长的时间让时钟转一圈,或者(b)您无法在一个时钟滴答内请求足够的guid来强制碰撞。
或者,您可以显示Guid中位之间的统计关系,或者Guid之间位的相关性。这样的关系可能使得算法很有可能是有缺陷的,而不一定能找到实际的碰撞。
当然,如果您只是想证明Guids可以碰撞,那么答案就是数学证明,而不是程序。
如果你想在代码的许多地方检查guid的唯一性,你可以使用一个漂亮的小扩展方法。
internal static class GuidExt
{
public static bool IsUnique(this Guid guid)
{
while (guid != Guid.NewGuid())
{ }
return false;
}
}
要调用它,只需调用Guid。每当你生成一个新的guid…
Guid g = Guid.NewGuid();
if (!g.IsUnique())
{
throw new GuidIsNotUniqueException();
}
...见鬼,我甚至建议打电话两次,以确保它在第一轮就得到了正确的答案。