독창적 인 임의의 정수에 의존 할 수 있습니까?


42

네트워크 프로토콜을 구현하고 있으며 패킷에 고유 식별자가 있어야합니다. 지금까지 임의의 32 비트 정수를 생성했으며 프로그램 / 연결 수명 동안 충돌이 발생할 가능성이 천문학적이라고 가정합니다. 이것은 일반적으로 프로덕션 코드에서 허용되는 관행으로 간주됩니까, 아니면 충돌을 방지하기 위해보다 복잡한 시스템을 고안해야합니까?


47
순차 정수를 사용하여 자르지 않는 이유는 무엇입니까?
whatsisname

20
왜 그냥 증가하는 int를 사용하지 않습니까? 설명하는 고유 속성을 갖도록 설계된 GUID 는 32 비트가 아닌 128 비트 크기입니다.
Robert Harvey

21
또는 연결된 각 컴퓨터에 채널 번호를 할당하고 증분 시퀀스 ID를 사용하십시오. 채널 번호와 함께 상위 비트를 차지하는 두 숫자는 새로운 고유 ID가됩니다.
Robert Harvey

27
"임의의 숫자 생성기" 가 다른 모든 숫자가 생성 될 때까지 특정 숫자가 반복되지 않도록 보장 하는 경우 이는 매우 잘못된 난수 생성기입니다! 같은 논리로, 동전 던지기의 "무작위"순서는 HTHTHTHTHT ....
alephzero

17
"패킷에 고유 식별자가 필요합니다"이 요구 사항을 위반하면 어떤 결과가 발생합니까? 고유 식별자가 필요한 경우 단어를 가장 엄격하게 읽을 때 중앙 집중식 시스템에서 식별자를 제거합니다 (MAC가 개별 네트워크 카드 회사에 할당되는 방식 등). 아마도 "필수"의 정의가 더 부드럽습니다. 그 부드러움 수준을 이해하면받는 답변이 크게 달라집니다.
Cort Ammon

답변:


142

생일 역설을 조심하십시오 .

크기 N 세트 (경우에 따라 N = 2 ^ 32)에서 임의의 값을 일관되게 (일관 적으로, 독립적으로) 생성한다고 가정합니다.

그런 다음 생일 역설 의 경험 법칙에 따르면 sqrt (N) 값에 대해 일단 생성하면 충돌이 발생할 가능성이 최소 50 % 일 수 있습니다. 즉, 두 개의 동일한 값이 생성 된 시퀀스.

N = 2 ^ 32의 경우 sqrt (N) = 2 ^ 16 = 65536입니다. 약 65k 개의 식별자를 생성 한 후 두 개가 충돌하지 않을 가능성이 높습니다! 초당 식별자를 생성하면 하루 미만으로 발생합니다. 말할 것도없이, 많은 네트워크 프로토콜이 그보다 빠르게 작동합니다.


11
+1. 마지막 작업에서 파트너 중 하나는 실제로이 접근 방식을 사용하여 임의의 식별자를 생성했습니다 (네트워킹 패킷이 아니라 최종 고객이 생성 한 공유 비즈니스 객체 용). 이를 향해 데이터를 쿼리했을 때 평균적으로 매일 2 ~ 3 개의 복제본이 있다는 것을 알았습니다. (다행히도, 복제본이 서로 4 시간 이내에 생성 된 경우에만 문제가 발생했습니다. 조금 덜 자주 발생했습니다. 그러나 여전히
그렇습니다

6
(수학을 렌더링하려면 여기를 클릭하십시오.) 가치가있는 $ \ sqrt {N} $ 근사값은 상수까지 정확합니다. $ N = 2 ^ {32} $의 경우 실제 임계 값은 77164입니다. 이는 $ \ prod_ {k = 1} ^ {n-1} (1-k / N)과 같이 $ n $의 가장 작은 값이므로 <1 / 2. $
wchargin

4
@ wchargin : 확률이 0.5를 치는 것에 대한 마법은 없습니다. 주목할만한 것은 N이 증가함에 따라 확률이 상대적으로 빠르게 증가한다는 것입니다. 만약 32 비트 식별자가 무작위 충돌의 경미하지만 사소한 확률을 가지면, 40 비트 식별자는 거의 없습니다.
supercat

3
@ supercat : 그게 다야. 방금 그러한 상수를 제공하면 정확한 값을 줄 수 있다고 생각했습니다. :-)
wchargin

2
@ wchargin : 중복에 대해 걱정해야 할 부분을 생각하는 것을 선호합니다. sqrt (N)보다 훨씬 아래로 내려 가면 랜덤 발생기에 심각한 결함이 없으면 충돌이 발생하지 않는다고 안전하게 말할 수있을 정도로 충돌 확률이 급격히 떨어집니다.
supercat

12

이 숫자에 충분한 비트가 있으면 고유 한 난수에 의존하는 것이 일반적으로 허용되는 것으로 간주됩니다. 난수를 반복하면 전체 보안이 손상되는 암호화 프로토콜이 있습니다. 그리고 난수 생성기에 사용되는 심각한 취약점이 없다면 문제가되지 않습니다.

UUID 생성 알고리즘 중 하나는 122 개의 임의 비트로 구성된 ID를 효과적으로 생성하고 고유 한 것으로 가정합니다. 다른 두 알고리즘은 고유 한 122 비트로 잘린 해시 값에 의존하며, 이는 거의 동일한 충돌 위험이 있습니다.

따라서 임의의 ID를 고유하게 만들기에 충분한 122 비트에 의존하는 표준이 있지만 32 비트로는 충분하지 않습니다. 32 비트 ID의 경우 충돌 위험이 50 %에 도달하기 전에 약 2¹⁶ ID 만 사용합니다. 2¹⁶ ID의 경우 각각 2³¹ 쌍에 가깝기 때문에 충돌 할 수 있습니다.

새로운 디자인에서 권장하는 것보다 122 비트도 적습니다. 일부 표준화를 따르는 것이 중요하다면 UUID를 사용하십시오. 그렇지 않으면 122 비트보다 큰 것을 사용하십시오.

160 비트 출력의 SHA1 해시 함수는 더 이상 안전한 것으로 간주되지 않습니다. 160 비트는 출력의 고유성을 보장하기에 충분하지 않기 때문입니다. 최신 해시 함수의 출력은 224에서 512 비트입니다. 무작위로 생성 된 ID는 동일한 크기를 목표로하여 안전 마진이 우수한 고유성을 보장해야합니다.


12
SHA-1은 무작위 충돌의 가능성이 높지 않고 무차별 대입보다 빠르게 충돌을 찾을 수있는 알고리즘 자체에 대한 특정 공격 (예 : 비 랜덤) 이 있기 때문에 안전하지 않은 것으로 간주됩니다 . 대략 122 비트와 초당 10 억 9 (10 ^ 9)의 ID 생성 속도로 인해 충돌의 50 % 확률에 도달하기까지 73 년이 걸린다고합니다.
8bittree

sqrt(2^122)= 2.3 quadrillion quadrillion UUID
noɥʇʎԀʎzɐɹƆ

2
@ 8bittree 비트 코인 네트워크는 10 분마다 2⁷⁰ SHA2 해시를 계산합니다. SHA1 해시 인 경우 충돌을 일으키는 데 1 주일 밖에 걸리지 않습니다. 비트 코인이 해시를 계산하는 것과 동일한 속도로 UUID가 생성 된 경우 충돌을 일으키는 데 2 ​​초 미만이 소요됩니다.
kasperd

Bitcoin은 충돌을 찾으려고 노력 하며 엄청난 인기를 얻었으며 해시를 찾기 위해 특별히 설계된 전용 하드웨어를 가지고 있습니다. 이제 OP가 널리 인기있는 암호 해독 또는 이와 유사한 것을 만들 계획이라면 ID 당 수백 또는 수천 비트가 필요할 수 있습니다. 그러나 표준 UUID 라이브러리가 충분하면 요구 사항이 필요하다고 가정하면 즉시 필요한 것보다 훨씬 많은 작업을 수행 할 수 있습니다.
8bittree

@ 8bittree 표준 라이브러리를 사용하는 것이 유리하다면 반드시 UUID를 선택하십시오. 그러나 임의의 바이트를 빼내는 urandom것은 UUID 라이브러리를 사용하는 것보다 더 효과적이지 않습니다. 방금 비교를 위해 둘 다 Python으로 구현했으며 각 메소드는 정확히 25 문자의 소스 코드였습니다.
kasperd

3

나는 이것을 나쁜 습관이라고 부를 것이다. 난수는 단순히 고유 한 숫자를 생성하지 않고 난수를 생성합니다. 무작위 분포에는 중복이 포함될 수 있습니다. 시간 요소를 추가하여이 상황을 수용하기 어렵게 만들 수 있습니다. 시스템 시계에서 현재 시간을 밀리 초 단위로 가져옵니다. 이 같은:

parseToInt(toString(System.currentTimeMillis()) + toString(Random.makeInt()))

먼 길을 갈 것입니다. 분명히 독창성을 보장하려면 UUID / GUID를 사용해야합니다. 그러나 랜덤 생성이 동일한 밀리 초에 복제본을 갖는 경우 오버랩의 유일한 가능성이기 때문에 생성 비용이 많이들 수 있습니다.


9
일부 시스템에서는 1ms가 오래 걸릴 수 있습니다.
quant_dev

7
이것은 실제로 충돌 가능성을 줄이지는 않습니다. N 개의 숫자 이후의 충돌 확률은 OP의 원래 솔루션의 확률과 정확히 같습니다. 현재 시간을 시드로 사용하는 트릭은 일반적으로 키를 순차적으로 할당 할 때 사용됩니다.
Cort Ammon

2
@Fresheyeball Random.makeInt ()이 실제로 정수의 최소값에서 정수의 최대 값까지 균일 한 분포를 생성하지 않는 한 효과가 없다고 확신합니다. 이 함수에 의해 생성 된 모든 과거 값에 대해 makeInt의 임의 값이 있습니다.이 정확한 시간 단계에 대해 해당 값을 생성하여 충돌을 생성합니다. makeInt의 모든 값은 동등 할 수 있으므로 충돌 확률은 시간을 추가하지 않은 충돌 확률과 정확히 같습니다.
Cort Ammon

2
@CortAmmon 이것은 현재 시간을 시드 로 사용 하지 않으며 타임 스탬프 부분이 다른 두 개의 숫자가 절대로 충돌 하지 않기 때문에 N 개의 숫자가 동일한 밀리 초 동안 모두 생성되지 않는 한 확실히 차이를 만듭니다 . 하루 미만의 시간 동안 충돌 확률이 50 % 인 초당 하나의 패킷에 대한 다른 답변의 예를 상상할 경우,이 패킷은 적어도 한 번에 currentTimeMillis감쌀 때까지 최대 1 %의 패킷에서 충돌 확률이 0 % 입니다.
hobbs

3
@hobbs 정수 오버플로를 잊어 버렸습니다. OP가 사용하는 키가 2 개의 정수를 포함하는 구조 (하나는 포함 System.currentTimeMillis하고 다른 하나는 포함 Random.makeInt()) 인 경우 충돌 가능성이 크게 줄어 듭니다. 그러나이 예제의 코드는 그렇지 않습니다. 주어 모든 전회 랜덤 값 및 모든 현재 시간, 충돌 확률은 처음에 충돌 개의 난수의 확률과 동일하다.
Cort Ammon

3

실패 확률과 실패 결과에 따라 다릅니다.

나는 하드웨어 사람들이 잘못된 결과를 낼 가능성이 작은 알고리즘 (100 년 동안 1 번의 실패와 같은 것)이 받아 들여질 것이라고 생각한 소프트웨어와 하드웨어 사람들 사이의 논쟁을 기억하고, 소프트웨어 사람들은 이것이 혐오라고 생각했다. 하드웨어 담당자는 정기적으로 예상되는 실패율을 계산했으며, 예를 들어 우주선으로 인한 교란으로 인해 모든 것이 때때로 잘못된 답을 줄 것이라는 생각에 매우 익숙했습니다. 그들은 소프트웨어 사람들이 100 %의 신뢰성을 기대한다는 것이 이상하다고 생각했습니다.


1

물론, 두 개의 임의의 32 비트 정수가 순차적으로 확률이 낮지 만 완전히 불가능하지는 않습니다. 적절한 엔지니어링 결정은 충돌 의 결과 , 생성하는 숫자의 양 추정, 고유성이 필요한 수명 및 악의적 인 사용자가 충돌을 시도하기 시작하면 어떻게되는지에 따라 결정됩니다.


0

임의의 숫자는 고유하다고 가정해도되지만주의해야합니다.

임의의 숫자가 균등하게 분포되어 있다고 가정하면 충돌 확률은 대략 (n 2 / 2) / k입니다. 여기서 n은 생성하는 임의의 숫자이고 k는 "임의"숫자가 취할 수있는 가능한 값의 수입니다.

천문학적으로는 숫자를 입력하지 않을 것이므로 2 30 분의 1 (대략 10 억)에이를 수 있습니다. 2 30 패킷 을 생성한다고 가정 해 봅시다 (각 패킷이 약 킬로바이트의 데이터를 나타내는 경우 총 1 테라 바이트의 총 데이터를 의미하지만 상상할 수는 없습니다). 최소 289 개의 가능한 값을 가진 난수가 필요하다는 것을 알았습니다 .

먼저 임의의 숫자가 충분히 커야합니다. 32 비트 난수는 최대 32 개의 가능한 값을 가질 수 있습니다 . 어디에도 근접하지 않은 사용량이 많은 서버의 경우.

둘째, 난수 생성기는 내부 상태가 충분히 커야합니다. 난수 생성기에 32 비트 내부 상태 만있는 경우 생성 한 값이 아무리 크더라도 최대 32 개의 가능한 값만 얻을 수 있습니다.

셋째, 연결 내에서가 아닌 연결 전체에서 난수가 고유해야하는 경우 난수 생성기를 잘 시드해야합니다. 프로그램이 자주 다시 시작되는 경우 특히 그렇습니다.

일반적으로 프로그래밍 언어의 "정규"난수 생성기는 이러한 용도에 적합하지 않습니다. 암호화 라이브러리에서 제공하는 난수 생성기는 일반적으로 있습니다.


0

위의 답변 중 일부에는 난수 생성기가 실제로 '평면'이라는 가정이 있습니다. 두 숫자가 다음에 생성 될 확률은 동일합니다.

대부분의 난수 생성기에는 해당되지 않습니다. 대부분은 시드에 반복적으로 적용되는 고차 다항식을 사용합니다.

즉, 일반적으로 UUID와 함께이 체계에 의존하는 많은 시스템이 있습니다. 예를 들어 Second Life의 모든 객체와 자산에는 임의로 생성 된 128 비트 UUID가 있으며 거의 ​​충돌하지 않습니다.


0

많은 사람들이 이미 높은 수준의 답변을 주었지만 몇 가지 사소한 점을 추가하고 싶습니다. 먼저 생일 역설에 관한 @nomadictype의 점은 훌륭 합니다.

또 다른 요점 : 무작위성은 사람들이 평상시 생각하는 것처럼 생성하고 정의하는 것만 큼 간단하지 않습니다. (실제로 무작위성에 대한 통계 테스트가 있습니다).

그럼에도 불구하고 사람들이 독립적 인 사건이 어떻게 든 서로에게 영향을 준다고 가정하는 통계적 오류 인 도박꾼의 오류를 인식하는 것이 중요합니다 . 랜덤 이벤트는 일반적으로 통계적으로 서로 독립적입니다. 즉, "10"을 무작위로 생성하더라도 향후 "10"을 더 많이 생성 할 확률은 변경되지 않습니다. (아마도 누군가 그 규칙에 대한 예외를 내놓을 수는 있지만 거의 모든 난수 생성기의 경우가 될 것으로 기대합니다).

내 대답은 충분히 긴 난수 시퀀스가 ​​고유하다고 가정 할 있다면 분명한 통계 패턴이기 때문에 실제로 난수는 아닐 것입니다. 또한 예를 들어 10을 생성하면 미래의 10을 생성 할 확률이 0 % (가능하지 않을 수 있음)가 될 것이므로 10 개의 새로운 숫자가 독립적 인 이벤트가 아니라는 것을 의미합니다. 즉, 10 이외의 숫자를 얻을 확률이 높아집니다 (즉, 생성하는 숫자가 많을수록 나머지 숫자 각각의 확률이 높아집니다).

한 가지 더 고려해야 할 사항 : 단일 게임에서 Powerball을 이길 수있는 기회는 내가 이해하는 것처럼 약 1 억 7 천 5 백만입니다. 그러나 누군가 이길 확률은 그보다 훨씬 높습니다. 특정 숫자 "승리"/ 복제 확률보다 누군가 "승리"(예 : 복제) 확률에 더 관심이 있습니다 .


모든 비트가 동일하거나 다른 식별자에서 생성 된 다른 비트와 독립적으로 0 또는 1이 될 가능성이있는 방식으로 4096 비트 식별자를 생성하는 경우 두 식별자가 일치 할 확률은 관측 가능한 우주에서 대략 4.0E81 개의 원자 각각에 대해 다른 식별자를 무작위로 생성하더라도 사라지는 것은 작습니다. 이러한 식별자가 거의 확실하게 고유하다는 사실은 어떤 식 으로든 "무작위"가되지 않을 것입니다.
supercat

@supercat 사실입니다. 충분히 많은 숫자가 주어지면 복제물이있을 가능성은 거의 없지만 불가능하지는 않습니다. OP가 설명하는 것이 좋은 아이디어인지 아닌지는 고유하지 않은 결과가 얼마나 나쁜지에 달려 있습니다.
EJoshuaS-복원 Monica Monica

랜덤 확률 충돌 확률이 유성 충돌 확률이 고유 ID에 의존하는 장치를 없애는 확률보다 작 으면 엔지니어링 관점에서 전자에 대해 걱정할 필요가 없습니다. 난수를 독립적으로 만들 수없는 것에 대해 걱정할 필요가 있지만, 랜덤 충돌은 문제가되지 않습니다.
supercat

@ supercat 나는 당신이 이것을 잘못 읽고 있다고 생각합니다. 생일 역설에 대한 다른 대답을보십시오. 나는 당신이 계산하는 것보다 훨씬 더 충돌이 있다고 생각합니다 .OP는 단지 32 비트 숫자를 사용하므로 어디 있는지 확실하지 않습니다. 에서 4096을 얻었고, nomadictype이 그 길이의 숫자와의 충돌 가능성이 실제로 놀랍도록 높다는 것을 보여주었습니다.
EJoshuaS-복원 Monica Monica

충돌을 완전히 수용 할 수없는 경우 작은 인구 집단의 경우에도 32 비트 숫자가 너무 짧은 것이 맞습니다. 충분히 큰 수를 사용하면 무작위 충돌의 가능성을 안전하게 막을 수있는 지점으로 줄일 수 있으며 많은 경우 더 많은 수를 사용하는 것이 다른 방법을 사용하는 것보다 낫습니다. 후자는 일반적으로 시스템의 시계가 재설정되거나 시스템이 백업에서 다시로드 되더라도 실행 취소하거나 롤백 할 수없는 상태 전이에 액세스해야하므로 고유성을 보장합니다.
supercat

0

사용하는 비트 수는 중요하지 않습니다. 두 개의 "임의"숫자가 다름을 보장 할 수 없습니다. 대신 컴퓨터의 IP 주소 또는 다른 네트워크 주소와 같은 일련 번호, 바람직하게는 HONKIN의 BIG 순차적 번호-128 비트 (분명히 부호가없는) 소리가 좋은 시작처럼 들리지만 256이 더 좋습니다.


-1

물론 아닙니다. rng을 교체하지 않고 샘플을 사용하지 않는 한 복제가 적을 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.