UUIDを使用して何かを一意に識別することはどの程度安全ですか(サーバーにアップロードされたファイルに使用しています)?私が理解しているように、それは乱数に基づいています。しかし、十分な時間を与えられれば、それは最終的には、たまたま純粋に偶然にも繰り返されるように思えます。この問題を軽減するためのより良いシステムまたは何らかのタイプのパターンはありますか?
UUIDを使用して何かを一意に識別することはどの程度安全ですか(サーバーにアップロードされたファイルに使用しています)?私が理解しているように、それは乱数に基づいています。しかし、十分な時間を与えられれば、それは最終的には、たまたま純粋に偶然にも繰り返されるように思えます。この問題を軽減するためのより良いシステムまたは何らかのタイプのパターンはありますか?
回答:
非常に安全:
隕石に当たる特定の人の年間リスクは、170億回に1回の確率と推定されます。つまり、確率は約0.00000000006(6×10 -11)であり、数十兆のUUIDを作成する確率に相当します。 1年で、1つの複製があります。つまり、今後100年間、毎秒10億個のUUIDを生成した後にのみ、複製が1つだけ作成される確率は約50%になります。
警告:
ただし、これらの確率は、十分なエントロピーを使用してUUIDが生成された場合にのみ保持されます。そうしないと、統計的分散が低くなる可能性があるため、重複の可能性が大幅に高くなる可能性があります。多くのデバイスからのデータがマージされてもUUIDが競合しないように、分散アプリケーションに一意の識別子が必要な場合、すべてのデバイスで使用されるシードとジェネレーターのランダム性は、アプリケーションの存続期間中信頼できる必要があります。これが実行できない場合、RFC4122は代わりに名前空間バリアントを使用することを推奨します。
出典:ユニバーサルユニーク識別子に関するWikipediaの記事のランダムなUUIDの重複セクション(リンクは、セクションを再編集する前の2016年12月の改訂にリンクしています)。
また、同じ普遍的に一意の識別子に関する記事Collisionsの同じ主題に関する現在のセクションも参照してください。
「十分な時間を与えられた」とは、100年を意味し、1秒あたり10億の割合でそれらを作成している場合、はい、100年後に衝突が発生する可能性は50%です。
UUIDには複数のタイプがあるため、「安全性」は、使用しているタイプ(UUID仕様では「バージョン」と呼ばれています)によって異なります。
バージョン1は、時間ベースおよびMACアドレスUUIDです。128ビットには、ネットワークカードのMACアドレス(製造元によって一意に割り当てられます)用の48ビットと、100ナノ秒の分解能を持つ60ビットクロックが含まれています。そのクロックは3603 ADでラップするため、これらのUUIDは少なくともそれまで安全です(1秒あたり1000万を超える新しいUUIDが必要な場合や、誰かがネットワークカードのクローンを作成する場合を除きます)。「少なくとも」と言うのは、時計が1582年10月15日に始まるため、時計がラップしてから400年ほど経ってから、重複の可能性が少しでもあるからです。
バージョン4は乱数UUIDです。6つの固定ビットがあり、残りのUUIDは122ビットのランダム性です。ウィキペディアまたはその他の分析を参照して、重複の可能性が非常に低いことを説明します。
バージョン3はMD5を使用し、バージョン5はランダムまたは疑似乱数ジェネレータの代わりにSHA-1を使用してこれらの122ビットを作成します。したがって、安全性の点では、バージョン4が統計的な問題であるようです(処理するダイジェストアルゴリズムが常に一意であることを確認する限り)。
バージョン2はバージョン1に似ていますが、クロックが小さいため、より早く循環します。ただし、バージョン2のUUIDはDCE用であるため、これらを使用しないでください。
したがって、すべての実用的な問題について、それらは安全です。確率に任せたくない場合(たとえば、生涯で地球が大きな小惑星によって破壊されるのを心配している人の場合)、バージョン1のUUIDを使用していることを確認してください。あなたの生涯において、あなたが3603 ADを過ぎて生きることを計画していない限り)。
では、なぜ誰もが単にバージョン1のUUIDを使用しないのですか?これは、バージョン1のUUIDが、それが生成されたマシンのMACアドレスを明らかにし、それらが予測可能になる可能性があるためです。
これに対する答えは、主にUUIDバージョンに依存する場合があります。
多くのUUIDジェネレーターは、バージョン4の乱数を使用します。ただし、これらの多くは乱数生成器の疑似を使用して生成します。
シードが不十分で期間が短いPRNGを使用してUUIDを生成する場合、それは非常に安全ではないと言えます。
したがって、それを生成するために使用されるアルゴリズムと同じくらい安全です。
反対に、これらの質問に対する答えがわかっている場合は、バージョン4のuuidを使用しても安全だと思います。実際、私はネットワークブロックファイルシステム上のブロックを識別するために使用しており、これまでのところ衝突はありません。
私の場合、私が使用しているPRNGはメルセンヌツイスターであり、/ dev / urandomを含む複数のソースからシードされる方法に注意しています。メルセンヌツイスターの周期は2 ^ 19937 − 1です。繰り返しのUUIDが表示されるまでには、非常に長い時間がかかります。
私は他の答えに同意します。UUIDは、ほぼすべての実用的な目的に対して十分に安全です1でであり、確かにです。
しかし、(仮説的に)そうではないと仮定します。
この問題を軽減するためのより良いシステムまたは何らかのタイプのパターンはありますか?
ここにいくつかのアプローチがあります:
より大きいUUIDを使用してください。たとえば、128のランダムビットの代わりに、256または512または...を使用します。タイプ4スタイルのUUIDに追加する各ビットは、信頼性の高いエントロピーソースがあると仮定して、衝突の確率を半分にします2。
UUIDを生成し、これまでに発行したすべてのサービスを記録する、集中型または分散型のサービスを構築します。新しいものを生成するたびに、UUIDが発行されたことがないことを確認します。そのようなサービスは、サービスを実行している人々が完全に信頼できる、腐敗しない、などと仮定すれば、技術的に簡単に実装できます(私はそう思います)。残念ながら、そうではありません...特に政府のセキュリティ組織が干渉する可能性がある場合はそうです。だから、このアプローチは、おそらく現実的ではない、あってもよい3現実の世界では不可能。
1-核ミサイルが自国の首都で発射されたかどうかがUUIDの一意性によって決定された場合、多くの仲間の市民は「確率が非常に低い」と確信していません。したがって、私の「ほぼすべて」の資格。
2-そしてここにあなたのための哲学的質問があります。本当にランダムなものはありますか?そうでない場合はどうすればわかりますか?私たちが知っている宇宙はシミュレーションですか?結果を変えるために物理法則を「微調整」する可能性がある神はいますか?
3-この問題に関する研究報告を誰かが知っている場合は、コメントしてください。
一意性をテストするためのテストスニペットを次に示します。@ scalabl3のコメントに触発されました
おもしろいことに、偶然、運、神の介入という驚異的なレベルで、同じ2行を続けて生成することができます。:Dはい、それは起こりません。複製を作成したその瞬間について考えるのは面白そうです。スクリーンショットビデオ!– scalabl3 2015年10月20日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のサブストリングはそうではないことに注意してください。
UUID4の場合、辺の長さが360,000 kmの立方体の箱に砂の粒があるのとほぼ同じ数のIDがあるようにします。これは、ジュピターの直径の約2 1/2倍の長さの辺を持つボックスです。
私がユニットを台無しにしたかどうか誰かが教えてくれるように働いています: