UUID를 사용하여 무언가를 고유하게 식별하는 것이 얼마나 안전합니까 (서버에 업로드 된 파일에 사용하고 있습니까)? 내가 이해하는 것처럼 난수를 기반으로합니다. 그러나 충분한 시간이 주어지면 결국 순수한 기회로 스스로 반복 할 것 같습니다. 이 문제를 완화하기 위해 더 나은 시스템이나 어떤 유형의 패턴이 있습니까?
UUID를 사용하여 무언가를 고유하게 식별하는 것이 얼마나 안전합니까 (서버에 업로드 된 파일에 사용하고 있습니까)? 내가 이해하는 것처럼 난수를 기반으로합니다. 그러나 충분한 시간이 주어지면 결국 순수한 기회로 스스로 반복 할 것 같습니다. 이 문제를 완화하기 위해 더 나은 시스템이나 어떤 유형의 패턴이 있습니까?
답변:
매우 안전:
주어진 사람이 운석에 부딪히는 연간 위험은 170 억으로 1 번의 확률로 추정되는데, 이는 확률이 약 0.00000000006 (6 × 10-11 )이며 이는 수십 조의 UUID를 생성 할 확률과 같습니다. 1 년 안에 하나의 사본을 가지고 있습니다. 다시 말해, 향후 100 년 동안 초당 10 억 개의 UUID를 생성 한 후에 만 하나의 복제본을 생성 할 확률은 약 50 %입니다.
경고:
그러나 이러한 확률은 충분한 엔트로피를 사용하여 UUID가 생성 된 경우에만 유지됩니다. 그렇지 않으면 통계 분산이 더 낮을 수 있으므로 복제 확률이 상당히 높아질 수 있습니다. 분산 응용 프로그램에 고유 식별자가 필요한 경우 많은 장치의 데이터를 병합하더라도 UUID가 충돌하지 않도록 모든 장치에 사용되는 시드 및 생성기의 임의성은 응용 프로그램 수명 동안 안정적이어야합니다. 이것이 가능하지 않은 경우 RFC4122는 네임 스페이스 변형을 대신 사용할 것을 권장합니다.
출처 : Wikipedia 기사에서 Universally 고유 식별자에 대한 중복 UUID 확률 섹션 (링크는 섹션을 재 작업하기 전에 2016 년 12 월부터 개정으로 이어짐)
또한 동일하게 고유 한 고유 식별자 기사 인 Collisions 의 동일한 주제에 대한 현재 섹션을 참조하십시오 .
"충분히 주어진 시간"이 100 년을 의미하고 초당 10 억의 비율로 생성한다면 100 년 후에 50 %의 확률로 충돌 할 가능성이 있습니다.
여러 유형의 UUID가 있으므로 "안전"은 사용중인 유형 (UUID 사양에서 "버전"이라고 함)에 따라 다릅니다.
버전 1은 시간 기반 MAC 주소 UUID입니다. 128 비트에는 네트워크 카드의 MAC 주소 (제조업체에서 고유하게 지정)에 대한 48 비트와 100 나노초의 해상도를 가진 60 비트 클록이 포함됩니다. 이 시계 는 3603 AD로 포장 되므로 이러한 UUID는 적어도 그때까지 안전합니다 (초당 1,000 만 개 이상의 새로운 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 버전에 크게 좌우 될 수 있습니다.
많은 UUID 생성기는 버전 4 난수를 사용합니다. 그러나 이들 중 다수는 Pseudo 난수 생성기를 사용하여 생성합니다.
UUID를 생성하는 데 짧은 기간의 시드가 잘못된 PRNG를 사용하면 전혀 안전하지 않다고 말할 수 있습니다.
따라서 알고리즘을 생성하는 데 사용 된 알고리즘만큼 안전합니다.
반대로,이 질문에 대한 답을 알고 있다면 버전 4 uuid가 사용하기에 안전해야한다고 생각합니다. 사실 나는 네트워크 블록 파일 시스템에서 블록을 식별하기 위해 그것을 사용하고 있으며 지금까지 충돌이 없었습니다.
필자의 경우, 사용중인 PRNG는 메르 센 트위스터이며 / dev / urandom을 포함한 여러 소스에서 나온 씨앗이 뿌리 내리는 방식에주의를 기울이고 있습니다. Mersenne twister의주기는 2 ^ 19937-1입니다. 반복되는 UUID를보기까지는 매우 오랜 시간이 걸릴 것입니다.
나는 다른 답변과 동의합니다. UUID는 거의 모든 실제적인 목적 1 , 그리고 확실히 당신의 목적을 위해 충분히 안전 합니다.
그러나 (가설 적으로) 그렇지 않다고 가정하십시오.
이 문제를 완화하기 위해 더 나은 시스템이나 어떤 유형의 패턴이 있습니까?
다음은 몇 가지 접근 방식입니다.
더 큰 UUID를 사용하십시오. 예를 들어, 대신 128 난수 비트의 사용 256 또는 512 또는 ... 당신은 유형 4 스타일에 추가하는 각 비트 UUID는 엔트로피의 신뢰할 수있는 원본이 있다고 가정, 반에 의해 충돌의 가능성을 줄일 수 2 .
UUID를 생성하고 발행 한 각각의 UUID를 기록하는 중앙 집중식 또는 분산 서비스를 구축하십시오. 새로운 것을 생성 할 때마다 UUID가 이전에 발행 된 적이 없는지 확인합니다. 우리가 서비스를 운영하는 사람들이 절대적으로 신뢰할 수 있고 부패 할 수 없다고 가정한다면 그러한 서비스는 기술적으로 간단합니다. 불행히도, 특히 정부의 보안 조직이 간섭 할 가능성이있는 경우에는 그렇지 않습니다. 그래서,이 방법은 아마 비현실적이며, 할 수있다 3 현실 세계에서 불가능합니다.
1-UUID의 독창성이 자국의 수도에서 핵 미사일을 발사했는지 여부를 결정하면 많은 동료 시민들이 "확률이 매우 낮다"고 확신하지 못할 것입니다. 따라서 나의 "거의 거의"자격.
2-여기 당신에게 철학적 인 질문이 있습니다. 진정으로 임의의 것이 있습니까? 그렇지 않은 경우 어떻게 알 수 있습니까? 우리가 알고있는 우주는 시뮬레이션입니까? 물리 법칙을 수정하여 결과를 바꿀 수있는 신이 있습니까?
3-이 문제에 대한 연구 논문을 아는 사람이 있으면 의견을 말하십시오.
다음은 고유성을 테스트하기위한 테스트 스 니펫입니다. @ 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/>
UUID4의 경우 길이가 360,000km 인 큐브 모양 상자에 모래 알갱이가있는만큼 ID가 거의 있도록합니다. 그것은 목성의 직경보다 ~ 2 1/2 배 긴 변을 가진 상자입니다.
내가 유닛을 엉망으로 만들 었는지 누군가가 말해 줄 수 있도록 노력하십시오.