UUID有多独特?

使用UUID唯一标识一些东西(我正在使用它来上传到服务器的文件)有多安全? 据我所知,它是根据随机数字。 然而,在我看来,如果有足够的时间,它最终会以纯粹的机会重复自我。 有一个更好的系统或某种types的模式来缓解这个问题?

非常安全:

一个被陨石击中的特定人的年度风险估计是170亿的一个机会,这意味着这个概率大概是0.00000000006(6×10 -11 ),相当于创造几十万亿UUID的几率在一年内有一个重复。 换句话说,在未来100年内每秒产生10亿个UUID之后,创build一个副本的可能性大约是50%。

警告:

但是,这些概率仅在使用足够的熵生成UUID时才成立。 否则,重复的概率可能会更高,因为统计分散可能会更低。 在分布式应用程序需要唯一标识符的情况下,即使合并来自多个设备的数据,UUID也不会发生冲突,因此每个设备上使用的种子和生成器的随机性在应用程序的生命周期内必须可靠。 在不可行的情况下,RFC4122build议使用名称空间变体。

资料来源: http : //en.wikipedia.org/wiki/UUID#Random_UUID_probability_of_duplicates

Wikepedia的文章已经删除了这一部分,但他们有一个有用的参考外部链接到其他地方: http ://www.h2database.com/html/advanced.html#uuid

如果“给定足够的时间”是指100年,而且以每秒十亿的速度创造它们,那么是的,100年后有50%的几率发生碰撞。

UUID有多种types,因此“安全性”取决于您使用的是哪种types(UUID规范所称的“版本”)。

  • 版本1是基于时间的MAC地址UUID。 128位包含网卡MAC地址(由制造商唯一分配)的48位和分辨率为100纳秒的60位时钟。 这个时钟包装在3603 AD中,所以这些UUID至less在这之前是安全的(除非你每秒需要超过1000万个新的UUID或者有人克隆你的网卡)。 我说“至less”是因为时钟从1582年10月15日开始,所以你在钟约四百年后才会有重复的可能性。

  • 版本4是随机数UUID。 有六个固定位,其余的UUID是122位的随机性。 请参阅维基百科或其他分析,描述极不可能的重复。

  • 版本3使用MD5,版本5使用SHA-1创build这些122位,而不是随机或伪随机数字发生器。 因此,就安全性而言,版本4是​​一个统计问题(只要确保摘要algorithm处理的内容始终是唯一的)。

  • 版本2与版本1类似,但是具有更小的时钟,所以它将更快地回绕。 但是由于版本2的UUID是DCE的,所以你不应该使用这些。

所以对于所有的实际问题他们是安全的。 如果你对把它放在可能性上感到不舒服(例如,你是担心地球在你的一生中被一个大型小行星毁坏的types),只要确保你使用的是版本1的UUID,并保证它是唯一的在你有生之年,除非你计划过活到公元3603年)。

那么为什么不是每个人都简单地使用版本1 UUID? 这是因为版本1的UUID会显示它生成的机器的MAC地址,并且它们是可预测的 – 这两件事情可能会对使用这些UUID的应用程序产生安全隐患。

这个答案很大程度上取决于UUID版本。

许多UUID生成器使用版本4的随机数。 然而,其中许多使用伪随机数发生器来生成它们。

如果使用一段时间很短的PRNG来生成UUID,我会说它不是很安全。

因此,它只与用于生成它的algorithm一样安全。

另一方面,如果你知道这些问题的答案,那么我认为第4版uuid应该是非常安全的使用。 事实上,我正在使用它来识别networking块文件系统上的块,到目前为止还没有发生冲突。

在我的情况下,我使用的PRNG是一个mersenne扭曲者,我很小心它的播种来自多个来源,包括/ dev / urandom。 梅森扭转者有一个2 ^ 19937 – 1的时期。这将是一个非常长的时间才会看到一个重复的uuid。

引用维基百科 :

因此,任何人都可以创build一个UUID,并使用它来确定某些事物,并确信这个标识符永远不会被任何人无意中使用

它继续详细解释它实际上是多么的安全。 所以要回答你的问题:是的,这是安全的。

UUIDscheme通常不仅使用伪随机元素,而且还使用当前的系统时间以及某些通常唯一的硬件ID(如果可用),例如networkingMAC地址。

使用UUID的重点在于,您相信它能够提供比您自己能够做到的唯一ID更好的工作。 这与使用第三方密码术库的原理相同,而不是自己的。 自己做,可能会更有趣,但是这样做通常不会那么负责任。

已经做了多年。 永远不会遇到问题。

我通常build立我的数据库有一个表,其中包含所有的关键和修改date等。 还没有遇到重复键的问题。

它唯一的缺点是当你正在写一些查询来快速地find一些信息时,你正在做大量的密钥复制和粘贴。 你不再有那么简单的记忆ID了。

这里有一个testing片段,供您testing它的uniquenes。 灵感来自@ scalabl3的评论

有意思的是,你可以连续产生2个相同的结果,当然在巧合程度,运气和神圣的介入水平上,尽pipe有不可思议的可能性,但它仍然是可能的! :D是的,这不会发生。 只是说当你创造一个重复的时候,想着那个时刻的乐趣! 截图video! – – scalabl3 15年10月20日在19:11

如果你感到幸运,选中checkbox,它只检查当前生成的ID。 如果您希望进行历史检查,请不要选中。 请注意,如果您不加限制,您可能会在某些时候用尽内存。 我试图让CPU友好,所以你可以在需要时快速中止,只需再次点击运行片断button或离开页面。

Math.log2 = Math.log2 || function(n){ return Math.log(n) / Math.log(2); } Math.trueRandom = (function() { var crypt = window.crypto || window.msCrypto; if (crypt && crypt.getRandomValues) { // if we have a crypto library, use it var random = function(min, max) { var rval = 0; var range = max - min; if (range < 2) { return min; } var bits_needed = Math.ceil(Math.log2(range)); if (bits_needed > 53) { throw new Exception("We cannot generate numbers larger than 53 bits."); } var bytes_needed = Math.ceil(bits_needed / 8); var mask = Math.pow(2, bits_needed) - 1; // 7776 -> (2^13 = 8192) -1 == 8191 or 0x00001111 11111111 // Create byte array and fill with N random numbers var byteArray = new Uint8Array(bytes_needed); crypt.getRandomValues(byteArray); var p = (bytes_needed - 1) * 8; for(var i = 0; i < bytes_needed; i++ ) { rval += byteArray[i] * Math.pow(2, p); p -= 8; } // Use & to apply the mask and reduce the number of recursive lookups rval = rval & mask; if (rval >= range) { // Integer out of acceptable range return random(min, max); } // Return an integer that falls within the range return min + rval; } return function() { var r = random(0, 1000000000) / 1000000000; return r; }; } else { // From http://baagoe.com/en/RandomMusings/javascript/ // Johannes Baagøe <baagoe@baagoe.com>, 2010 function Mash() { var n = 0xefc8249d; var mash = function(data) { data = data.toString(); for (var i = 0; i < data.length; i++) { n += data.charCodeAt(i); var h = 0.02519603282416938 * n; n = h >>> 0; h -= n; h *= n; n = h >>> 0; h -= n; n += h * 0x100000000; // 2^32 } return (n >>> 0) * 2.3283064365386963e-10; // 2^-32 }; mash.version = 'Mash 0.9'; return mash; } // From http://baagoe.com/en/RandomMusings/javascript/ function Alea() { return (function(args) { // Johannes Baagøe <baagoe@baagoe.com>, 2010 var s0 = 0; var s1 = 0; var s2 = 0; var c = 1; if (args.length == 0) { args = [+new Date()]; } var mash = Mash(); s0 = mash(' '); s1 = mash(' '); s2 = mash(' '); for (var i = 0; i < args.length; i++) { s0 -= mash(args[i]); if (s0 < 0) { s0 += 1; } s1 -= mash(args[i]); if (s1 < 0) { s1 += 1; } s2 -= mash(args[i]); if (s2 < 0) { s2 += 1; } } mash = null; var random = function() { var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32 s0 = s1; s1 = s2; return s2 = t - (c = t | 0); }; random.uint32 = function() { return random() * 0x100000000; // 2^32 }; random.fract53 = function() { return random() + (random() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53 }; random.version = 'Alea 0.9'; random.args = args; return random; }(Array.prototype.slice.call(arguments))); }; return Alea(); } }()); Math.guid = function() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = Math.trueRandom() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); }; function logit(item1, item2) { console.log("Do "+item1+" and "+item2+" equal? "+(item1 == item2 ? "OMG! take a screenshot and you'll be epic on the world of cryptography, buy a lottery ticket now!":"No they do not. shame. no fame")+ ", runs: "+window.numberofRuns); } numberofRuns = 0; function test() { window.numberofRuns++; var x = Math.guid(); var y = Math.guid(); var test = x == y || historyTest(x,y); logit(x,y); return test; } historyArr = []; historyCount = 0; function historyTest(item1, item2) { if(window.luckyDog) { return false; } for(var i = historyCount; i > -1; i--) { logit(item1,window.historyArr[i]); if(item1 == history[i]) { return true; } logit(item2,window.historyArr[i]); if(item2 == history[i]) { return true; } } window.historyArr.push(item1); window.historyArr.push(item2); window.historyCount+=2; return false; } luckyDog = false; document.body.onload = function() { document.getElementById('runit').onclick = function() { window.luckyDog = document.getElementById('lucky').checked; var val = document.getElementById('input').value if(val.trim() == '0') { var intervaltimer = window.setInterval(function() { var test = window.test(); if(test) { window.clearInterval(intervaltimer); } },0); } else { var num = parseInt(val); if(num > 0) { var intervaltimer = window.setInterval(function() { var test = window.test(); num--; if(num < 0 || test) { window.clearInterval(intervaltimer); } },0); } } }; }; 
 Please input how often the calulation should run. set to 0 for forever. Check the checkbox if you feel lucky.<BR/> <input type="text" value="0" id="input"><input type="checkbox" id="lucky"><button id="runit">Run</button><BR/> 

我不知道这对你是否重要,但请记住, GUID是全局唯一的,但GUID的子string不是 。