题
使用 UUID 唯一标识某些内容(我将其用于上传到服务器的文件)有多安全?据我了解,它是基于随机数的。然而,在我看来,只要有足够的时间,它最终会重演,纯粹是偶然。是否有更好的系统或某种类型的模式来缓解这个问题?
解决方案
非常安全:
一个特定的人的年度风险被陨石击中的 据估计,在17个十亿分之一的机会,这意味着 概率约为0.00000000006(6×10 -11 ),相当于赔率 在每年创造几十的UUID万亿,并具有一 重复。换句话说,生成1点十亿的UUID每次只后 第二在未来100年里,创建只是一个概率 重复将是约50%。
警告:
但是,这些概率只能容纳产生的UUID时 使用足够的熵。否则,重复的可能性 可能是显著更高,因为统计分散可能 更低。其中唯一标识符所需的分布 应用,使的UUID不冲突,即使从许多数据 装置被合并,将种子和发电机的随机性使用上 每个设备必须是可靠的应用程序的生命。哪里 这是不可行的,RFC4122建议使用一个命名空间变异 代替。
来源: 重复的随机UUID概率的部分通用唯一标识符(链接指向一个版本从2016年12月之前,编辑修改了部分)。
维基百科文章的另见当前段上的相同的通用唯一标识符制品, 相同被摄体碰撞 。
其他提示
如果用“足够的时间”你的意思是100年,你在一个十亿的速度第二创建它们,那么,你必须有经过100多年的冲突的可能性为50%。
有多种类型的积极,所以"安全"取决于哪种类型(其中usb驱规范叫"版本")。
第1版是基于时间加MAC地址usb驱.128位包含48个位于网络卡MAC地址的(这是唯一由制造商分配)和60位时分辨率为100纳秒。这个时钟 包裹在3603A.D. 因此这些付是安全的至少到那时(除非你需要10多万新的付每秒或某人的克隆的网络卡)。我说"至少",因为时开始,在15October1582,所以你有大约400年之后的时钟包裹之前,甚至有一个小的可能性重复。
第4版是随机数usb驱.有六个固定的位和其他的东的122位的随机性。看看 维基百科 或其他的分析,说明如何非常不太可能有重复。
第3版是使用MD5和第5版的使用SHA-1以建立的那些122位,而不是一个随机或伪随机数发生器。因此,在安全方面也是一样的版本4是统计问题(如你确定什么样的摘要算法是处理始终是唯一的).
版本2类似于第1版,但有一个小时钟的所以它要围绕更快。但是从版本2的付是为DCE,你不应该使用这些。
因此,对于所有实际问题他们是安全的。如果你不离开它概率(例如您是种类型的人担心的地球上越来越被摧毁的一个大的小行星在你的一生),只要确定你使用一个版本1usb驱,它保证是唯一的(在你的一生,除非计划居住过去的3603A.D).
那么,为什么不是每个人只需使用的版本1付?这是因为,第1版付揭示MAC地址的机生成,他们可以可预测的--两个东西,可能会产生安全影响的应用程序使用这些付.
这个问题的答案可以在UUID版本很大程度上取决于。
许多UUID发电机使用版本4的随机数。然而,许多这些使用伪随机数生成器来生成它们。
如果接种的不良PRNG用小周期用于生成UUID我会说这是不是很安全的。
因此,这只是为安全所用的算法来生成它。
在另一面,如果你知道这些问题的答案,然后我觉得一个版本4的UUID应该是非常安全的使用。事实上,我用它来识别网络块的文件系统块,到目前为止还没有发生冲突。
在我的情况下,我使用的PRNG是一个Mersenne扭曲和林小心与它的接种的方式是从多个来源,包括的/ dev / urandom的。梅森倍捻机具有周期为2 ^ 19937的 - 1,这将是一个非常非常长的时间之前,我看到一个重复的UUID
这维基百科:
因此,任何人都可以创建一个UUID和使用 它来识别用的东西 合理的信心, 标识将永远 无意间使用任何人 别的
它接着解释它实际上是如何安全的相当不错的细节。因此,要回答你的问题:是的,它是足够安全的。
UUID方案通常不仅使用伪随机元素,也是当前的系统时间,以及某种经常唯一硬件ID,如果可用,诸如网络的MAC地址。
使用UUID的整点是,你相信它做提供比你一个唯一的ID自己将能够做的更好的工作。这是支持使用第三方加密库,而不是滚动您自己同样的理由。做你自己可能会更有趣,但它通常不太负责任的这样做。
已经做了好几年了。从来没有碰到一个问题。
我通常设置我的DB的有一个包含所有按键和修改的日期和这样的一个表。有没有碰到过重复键的问题。
这是它唯一的缺点是,当你正在写一些查询找到一些信息很快你做了很多按键的复制和粘贴。你不必短易记的ID了。
下面是一个测试片段您测试它的唯一性。 通过@ scalabl3的评论启发
有趣的是,你可以生成一排,在巧合,运气和神助的令人难以置信的水平是相同的,当然2,然而,尽管深不可测的几率,它仍然是可能的! :d是的,它不会发生。只是说对想那一刻,当你创建一个重复的娱乐!截图视频! - scalabl3年10月20 '15在19:11
如果你感到幸运,选中该复选框,它只检查当前生成的ID。如果你希望一个历史确认,不要选择它。 请注意,你可能会在某个时候,如果你不要选择它用完内存。我试图使它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/>
我同意其他的答案。付是不够安全,为几乎所有的实际目的1, ,并肯定为你的。
但是,假设(假设),他们不是。
是否有一个更好的系统或一个模式的某种类型,以减轻这一问题?
这里有几种方法:
使用一个更大的usb驱.例如,而不是一个128随机的位,使用256或512或者...各位你在添加一个类型-4式usb驱将减少碰撞的概率的一半,假定你有一个可靠的来源的熵2.
建立一个集中或分散的服务,产生应付并记录每一个它已经发出。每次产生一个新的一个,检查usb驱从未颁发之前。这种服务将在技术上直接实现(我认为)如果我们假定,人们运行的服务是绝对可信,廉洁等等。不幸的是,他们不是...尤其是当有可能是政府干扰。因此,这种做法可能是不切实际的,并且可以3 不可能在真实的世界。
1-如果唯一的应付确定是否核导弹有发起了在你们国家的首都城市里,有很多你的同胞们不会相信通过"的概率是非常低"。因此我的"几乎所有"资格。
2-这里是一个哲学问题。为什么没有真正随机的?我们怎么会知道如果不是?是宇宙,因为我们知道这一模拟?是否有一个上帝,他可能"调整"的法律的物理改变的一个结果?
3-如果有人知道的任何研究文件,关于这个问题,请评论。
我不知道这对你是否重要,但请记住 GUID 是全局唯一的,但 GUID 的子字符串不是.