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