使用UUID唯一标识某些内容(我正在使用它来标识上传到服务器的文件)有多安全?据我所知,它是基于随机数。然而,在我看来,只要有足够的时间,它最终会完全偶然地重复它自己。是否有更好的系统或某种类型的模式来缓解这个问题?
当前回答
我应该提一下,我在亚马逊上买了两个外接希捷驱动器,它们有相同的设备UUID,但PARTUUID不同。大概他们用来格式化硬盘的克隆软件也复制了UUID。
显然,UUID冲突更可能是由于有缺陷的克隆或复制过程而不是由于随机巧合而发生。在计算UUID风险时请记住这一点。
其他回答
这里有一个测试片段供您测试它的独特性。 灵感来自@scalabl3的评论
有趣的是,你可以连续生成2个完全相同的结果,当然是在令人难以置信的巧合、运气和神的干预下,尽管有不可思议的几率,但这仍然是可能的!:是的,不会发生的。我这么说只是为了好玩,想想你创造了一个复制品的那一刻!视频截图!- scalab13 10月20日15日19:11
如果您觉得幸运,请选中复选框,它只检查当前生成的id。如果您希望进行历史记录检查,请不勾选。 请注意,如果您不勾选它,您可能会在某些时候耗尽ram。我试图使它对cpu友好,以便在需要时可以快速中止,只需再次点击运行代码片段按钮或离开页面。
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的子字符串不是。
我同意其他的答案。uuid对于几乎所有的实际用途都是足够安全的,当然对你来说也是如此。
但假设(假设)它们不是。
是否有更好的系统或某种类型的模式来缓解这个问题?
这里有一些方法:
Use a bigger UUID. For instance, instead of a 128 random bits, use 256 or 512 or ... Each bit you add to a type-4 style UUID will reduce the probability of a collision by a half, assuming that you have a reliable source of entropy2. Build a centralized or distributed service that generates UUIDs and records each and every one it has ever issued. Each time it generates a new one, it checks that the UUID has never been issued before. Such a service would be technically straight-forward to implement (I think) if we assumed that the people running the service were absolutely trustworthy, incorruptible, etcetera. Unfortunately, they aren't ... especially when there is the possibility of governments' security organizations interfering. So, this approach is probably impractical, and may be3 impossible in the real world.
1 - If uniqueness of UUIDs determined whether nuclear missiles got launched at your country's capital city, a lot of your fellow citizens would not be convinced by "the probability is extremely low". Hence my "nearly all" qualification. 2 - And here's a philosophical question for you. Is anything ever truly random? How would we know if it wasn't? Is the universe as we know it a simulation? Is there a God who might conceivably "tweak" the laws of physics to alter an outcome? 3 - If anyone knows of any research papers on this problem, please comment.
我应该提一下,我在亚马逊上买了两个外接希捷驱动器,它们有相同的设备UUID,但PARTUUID不同。大概他们用来格式化硬盘的克隆软件也复制了UUID。
显然,UUID冲突更可能是由于有缺陷的克隆或复制过程而不是由于随机巧合而发生。在计算UUID风险时请记住这一点。
这个问题的答案很大程度上取决于UUID版本。
许多UUID生成器使用版本4的随机数。然而,其中许多使用伪随机数生成器来生成它们。
如果使用一个短周期的低种子PRNG来生成UUID,我认为这一点都不安全。一些随机数生成器的方差也很差。也就是说,更倾向于某些数字。这不会有好结果的。
因此,它的安全性取决于生成它的算法。
另一方面,如果您知道这些问题的答案,那么我认为使用版本4的uuid应该是非常安全的。事实上,我正在使用它来识别网络块文件系统上的块,到目前为止还没有发生冲突。
在我的情况下,我使用的PRNG是一个梅森龙卷风,我很小心,它的播种方式是来自多个来源,包括/dev/ urrandom。梅森龙卷风的周期为2^19937−1。在我看到一个重复的uuid之前,会有很长很长的时间。
因此,选择一个好的库或自己生成它,并确保使用合适的PRNG算法。
推荐文章
- 什么时候我应该在python中使用uuid.uuid1() vs. uuid.uuid4() ?
- GUID / UUID数据库键的优缺点
- PHP函数生成v4 UUID
- Guid都是0 (0)?
- GUID不是唯一的简单证明
- 从Swift生成iOS上的UUID
- Java的UUID.randomUUID有多好?
- 如何测试有效的UUID/GUID?
- Guid. newguid () vs. new Guid()
- 使用GUID作为主键的最佳实践是什么,特别是在性能方面?
- 用Java创建一个GUID
- 使用哪个UUID版本?
- GUID的字符串长度是多少?
- 如何生成一个随机的,唯一的,字母数字字符串?
- 在Postgres中为插入语句生成UUID ?