UUID冲突[关闭]


33

鉴于我们使用的随机数生成器不是真正的随机数,并且我们可能有数十台或数百台运行相同代码的相同机器,是否有人对UUID冲突的可能性进行了任何真正的研究,尤其是对于版本4(随机)UUID?生成UUID?

我的同事认为测试UUID冲突是完全浪费时间,但是我总是输入代码以从数据库中捕获重复的键异常,然后尝试使用新的UUID。但是,如果UUID来自另一个进程并引用一个真实对象,那将无法解决问题。


4
该问题已在Stack Overflow:stackoverflow.com/questions/3038023/…上得到了回答,如显示的基本Google搜索:google.com/search?
q=uuid+collision

3
这个问题是关于SQL * Server中使用的特定算法的,这绝对不是版本4(随机)。我在问具体的版本4。
Paul Tomblin,2012年

您是说SQL Server NEWID()函数的实现不是随机的吗?如果是这样,您是否有任何来源来支持此类索赔?对我来说,其输出显然类似于v4 UUID。NEWSEQUENTIALID()绝对不是完全随机的,但这是它的目的:生成可以很好地(至少与UUID一样)用作索引键的UUID。
CVn 2012年

1
我正在寻找链接问题的答案,该问题指出NEWID()包含mac地址的某些位,这使其成为V1或V2 UUID,而不是V4。
Paul Tomblin,2012年

2
这个问题似乎不合时宜,因为它与互联网,书籍尤其是StackOverflow上已经讨论过的广告馆有关

Answers:


18

维基百科有一些细节:

http://en.wikipedia.org/wiki/Universally_unique_identifier

http://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_duplicates

但是,只有当比特完全随机时,概率才成立。但是,在另一个答案中链接的RFC http://tools.ietf.org/html/rfc4122#page-14对此版本4进行了定义:

“ 4.4。版本4 UUID用于从真正随机或伪随机数生成UUID。将其他所有位设置为随机(或伪随机)选择的值。

这几乎允许从xkcd随机生成器http://xkcd.com/221/到使用量子噪声的硬件设备进行任何操作。RFC中的安全注意事项:

“ 6.在各种主机上生成UUID的分布式应用程序必须愿意依赖所有主机上的随机数源。如果这不可行,则应使用名称空间变量。”

我的读为:您是一个人。您要对自己的应用程序中的随机生成器负责,但这和其他任何事情都基于信任。如果您不信任自己正确理解和使用所选随机生成器的能力,那么检查冲突确实是个好主意。如果您不信任其他进程的程序员,请检查冲突或使用其他UUID版本。


11

当然,您应该检测是否发生冲突,并且如果发生冲突,则您的应用程序应引发异常。例如,如果将UUID用作数据库中的主键,则在插入冲突ID时数据库应引发错误。

但是,我相信编写代码以在发生冲突时生成新的UUID并再次尝试浪费时间。发生碰撞的机会非常小,以至于引发异常将是处理该异常的一种完全合理的方式。

请记住,这不仅浪费您的代码编写时间,而且还会使代码变得更加复杂,使下一个人阅读起来更加困难,几乎毫无收获。


2
您的UUID仅与随机生成器一样好。对于非常(非常)糟糕的情况,不仅会发生碰撞,而且是不可避免的。话虽如此,也许在世代时检查重复确实是过高的,但我希望这种情况会发生,而且我认为并没有太多要求。在某些领域(例如医疗保健),我认为有必要拥有能够捕获此类情况的代码(例如数据库中的冲突检测)。您会惊讶于我花了多少时间调试从未发生过的情况。
Newtopian 2012年

1
我想我没有说清楚。我更新了答案,使其更加明确。
皮特

7

这个问题问得好。我认为在匆忙中随处使用UUID并没有得到充分考虑。我尚未找到任何可靠的研究。

一个建议:在这里非常小心,并充分了解您的密码学。如果您使用128位的UUID,则“生日效应”会告诉我们,生成大约2 ^ 64个密钥后,如果每个密钥中都有128位的熵,则很可能发生冲突。

要确保确实如此,实际上是相当困难的。真正的随机性可以由以下因素产生:(a)放射性衰变(b)经常被污染的随机本底无线电噪声,除非您小心谨慎(c)适当选择的电子噪声,例如取自反向偏置的齐纳二极管。(我已经玩过最后一款了,它的工作原理就像是一种魅力,顺便说一句)。

我不会信任诸如“我一年没有见过”之类的声明,除非用户生成了接近2 ^ 64(即大约10 ^ 19)个密钥的东西,并相互对照检查,非平凡的运动。

问题是这样的。假设您将密钥与其他人在同一个密钥空间中生成的所有其他密钥进行比较时,熵只有100位。您将开始在大约2 ^ 50即看到碰撞。大约10 ^ 15个键。如果仅用1万亿个键填充数据库,则发生冲突的机会仍然可以忽略不计。而且,如果您不进行检查,那么以后您将收到意外错误,这些错误会蔓延到Peta行大小的数据库中。这可能很难咬。

有多种生成此类UUID的方法这一事实应引起暂时的关注。当您意识到很少有生成器使用类型4 UUID具有足够熵的“真正随机”过程时,您应该过分担心,除非您仔细检查了生成器的熵含量。(大多数人不会这样做,甚至不知道如何做;您可能会从DieHarder套件开始)。不要将伪随机数生成与真正的随机数生成混淆。

至关重要的是,您必须意识到所放入的熵就是所拥有的熵,并且仅通过应用加密函数来扰动密钥就不会改变熵。如果我的整个空间都包含数字0和1,那么熵的内容与以下两个字符串的熵内容相同(如果仅有的两种选择),可能并不直观直观:“这是一个非常复杂的字符串293290729382832 * !@@#&^%$$),. m}”和“现在完全不同”。仍然只有两个选择。

随机性是很难正确的,并且仅仅相信“专家们已经看过了,所以就可以了”可能是不够的。专家密码学家(其中很少有真正精通的专家)是第一个承认他们经常弄错的人。我们信任heartbleed,DigiNotar等。

我认为Paul Tomblin正在采取适当的谨慎态度。我的2c。


6

您遇到的问题是,如果您使用“随机数生成器”并且不知道该生成器的随机性,那么实际上碰撞的可能性是未知的。如果随机数生成器以某种方式相关,则碰撞的可能性可能会急剧增加-可能很多很多数量级或大小。

即使发生碰撞的可能性很小,也存在一个基本问题:该可能性不为0。这意味着碰撞最终会发生,它们不会经常发生。

生成和使用UUID的频率越高,越容易看到冲突。(在其他所有条件不变的情况下,每年生成1个表示比每秒生成一百万个表示的等待时间更长)。

如果该概率是有限的,未知的,并且您使用了很多UUID,那么您需要考虑碰撞的后果。如果引发异常并关闭业务应用程序是不可接受的,那就不要这样做!(我脑海中浮现的例子是:“可以在更新库签入的过程中关闭Web服务器...这不会经常发生。”和“可以在更新过程中关闭薪资系统。这些决定可能是限制职业发展的举动。)

但是,根据您的应用程序,情况可能更糟。如果您测试是否存在UUID(即进行查找),然后在尚未存在的情况下进行新的创建(这是一件很常见的事情),那么您可能会发现自己正在链接记录或建立关系,实际上您是通过不应该连接的UUID连接2件东西。在这种情况下,引发异常将无法解决任何问题,并且您在某处创建了无法检测的混乱。这种事情会导致信息泄漏,并且非常尴尬。(例如:登录到您的银行,发现您可以看到别人帐户的余额!不好!)

简介:您需要考虑UUID的使用方式以及碰撞的后果。这决定了您是否应该注意检测并避免碰撞,在发生碰撞时采取一些简单的措施,或者什么也不做。在某些情况下,简单,单一,适合所有人的解决方案可能不合适。


2
“(碰撞的可能性)不为0”任何有限长度的序列都具有此属性。即使有一个完全随机v4的UUID,一旦你产生2 ^ 122唯一的UUID(128位减4位版本减去2保留位),在下次生成一个被保证是一个碰撞。您很可能会比那早撞到碰撞。更大的问题是,像5e36重复这样的事情之后发生的碰撞是否是一个问题,并且无法普遍解决(尽管在每种情况下显然都有可能回答),就像您在总结中所说的那样。
CVn 2012年

当然。这是显而易见的陈述(但仍需重复)。问题是与随机数生成器有多少相关性。这可能会大大增加碰撞的可能性(2 ^大),但是除非您进行大量的挖掘,研究或计算,否则您将不知道会有多少。假设碰撞的可能性远比最佳可能性差,则最好谨慎。之后……您需要考虑后果。
quick_now 2012年

0

涉及两个问题:

  1. 使用的随机数生成器的质量。

  2. 可能生成的UUID数量。

“随机” UUID具有122个随机位。假设完全随机性,则可以预期在大约2 ^ 61个生成的UUID(即2 ^ 122的平方根)处发生第一次冲突。如果地球上每个人每秒都要生成一个UUID,那么每年便有10,000,000,000 * 365 * 24 * 60 * 60 = 315360000000000000个UUID,这非常接近2 ^ 58。也就是说,几年后,您将首次碰撞。除非您的应用程序接近这些数字,否则您可以确定,如果您的随机生成器质量不错,则不会发生冲突。

谈论随机数生成器:如果您使用标准C库生成器(直接,间接或类似的生成器),并且可能随时间播种它们,那么您会很生硬。这些不能利用足够的熵来避免冲突。但是,如果您使用的是Linux,则只需从读取16个字节的数据/dev/urandom:这将利用内核搅动的熵池,该池可以访问某些实际的随机事件。除非您通常在引导序列的早期真正地生成UUID,/dev/urandom否则其行为应类似于真正的随机源。


-1

我曾经使用一个非常简单的(强力)程序对其进行过测试,该程序生成了1000万个UUID,而且我还没有遇到碰撞。

UUID RFC说,UUID不只是一堆(伪)随机数。


1
我要问的版本4,几乎是一堆随机数,除了6位在所有这些位上都是完全一样的。
Paul Tomblin,2012年

8
1000万甚至不是九牛一毛。3E30中发生碰撞的几率只有1分之一。如果您找到了,我建议您尽快购买每张彩票中的彩票!
罗斯·帕特森

@RossPatterson,我特别想知道的是,如果您有数百台计算机在相同的硬件上使用完全相同的伪随机算法,则会大大增加碰撞的几率。我怀疑会。
Paul Tomblin,2012年

1
@Paul-只有在初始播种过程中熵不足的情况下,我才想过-例如,如果仅从一天中的某个时间生成种子,并且所有机器都在同一时刻启动。我非常怀疑播种是否这么弱-甚至有可能使用了硬件序列号,这当然对于每台机器都是唯一的。
2012年

1
las,播种可能非常薄弱。Linux系统喜欢从高度随机的源(设备驱动程序活动)中播种PRNG ,但是在其他环境中,标准是使用当前时间戳,如果时间戳与足够多的机器保持紧密时间同步,则可能会成为问题。
罗斯·帕特森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.