UUIDの衝突[終了]


33

特にバージョン4(ランダム)UUIDを使用して、UUID衝突の可能性について誰もが実際の研究を行いました。使用する乱数ジェネレーターが真にランダムではなく、同じコードを実行する数十または数百の同一マシンがある可能性があるためですUUIDを生成しますか?

私の同僚は、UUID衝突のテストは完全に時間の浪費であると考えていますが、データベースから重複キー例外をキャッチして新しいUUIDで再試行するコードを常に入れています。しかし、UUIDが別のプロセスから来て実際のオブジェクトを参照している場合、問題は解決しません。


4
質問はすでにStack Overflowで回答されています:stackoverflow.com/questions/3038023/…、基本的なGoogle検索を示しています:google.com/search
q=uuid+collision

3
その質問は、SQL * Serverで使用される特定のアルゴリズムに関するものであり、バージョン4(ランダム)ではありません。バージョン4について具体的に尋ねています。
ポールトンブリン

SQL ServerのNEWID()関数の実装はランダムではないと言っていますか?その場合、そのような主張を裏付ける情報源はありますか?その出力は明らかにv4 UUIDのように見えます。NEWSEQUENTIALID()明らかに完全にランダムではありませんが、それはその目的です:インデックスキーとして(少なくともUUIDと同様に)うまく機能するUUIDを生成することです。
CVn

1
NEWID()にはMACアドレスの一部のビットが含まれているため、V4ではなくV1またはV2 UUIDになっているというリンクされた質問への回答があります。
ポールトムブリン

2
それは、すでに本で、特にStackOverflowの上で、インターネット上の広告nauseumを議論何かについてであるので、この質問は、オフトピックのように見える

回答:


18

ウィキペディアにはいくつかの詳細があります。

http://en.wikipedia.org/wiki/Universally_unique_identifier

http://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_duplicates

ただし、ビットが完全にランダムである場合にのみ、確率が保持されます。ただし、他の回答にリンクされているRFC http://tools.ietf.org/html/rfc4122#page-14は、バージョン4に対してこれを定義しています。

「4.4。[...]バージョン4 UUIDは、真の乱数または擬似乱数からUUIDを生成するためのものです。[...]他のすべてのビットをランダムに(または擬似ランダムに)選択した値に設定します。

これにより、xkcdランダムジェネレーターhttp://xkcd.com/221/から量子ノイズを使用するハードウェアデバイスまで、あらゆることが可能になります。RFCのセキュリティに関する考慮事項:

「6.さまざまなホストでUUIDを生成する分散アプリケーションは、すべてのホストで乱数ソースに依存する必要があります。これが実行可能でない場合は、名前空間バリアントを使用する必要があります。」

私はこれを次のように読みます:あなたは自分でしています。あなたはあなた自身のアプリケーション内であなたのランダムジェネレーターに責任がありますが、これと他のものは信頼に基づいています。選択したランダムジェネレーターを正しく理解して使用する自分の能力を信用しない場合は、衝突をチェックすることをお勧めします。他のプロセスのプログラマを信頼していない場合は、衝突をチェックするか、別のUUIDバージョンを使用してください。


11

衝突が発生したかどうかを確実に検出し、発生した場合はアプリケーションで例外をスローする必要があります。たとえば、UUIDがデータベースの主キーとして使用されている場合、衝突するIDを挿入すると、データベースでエラーがスローされます。

ただし、衝突が発生した場合に新しいUUIDを生成するためのコードを記述し、時間を無駄にしようとすると信じています。衝突が発生する可能性は非常に小さいので、例外をスローすることは完全に合理的な方法で対処できます。

覚えておいてください、それはコードを書くあなた自身の時間の無駄であるだけでなく、コードをより複雑にし、次の人が読むのをより難しくし、ほとんど利益を得ません。


2
UUIDは、ランダムジェネレーターと同じくらい優れています。非常に(非常に)貧弱な1つの衝突では、衝突が発生するだけでなく、避けられません。おそらく、生成時に重複をチェックするのは本当にやり過ぎだろうと言ったが、状況が発生する可能性があることを期待しており、私の意見では、それほど要求することはない。一部のドメイン(たとえば、ヘルスケア)では、このような状況をキャッチするコード(データベースでの衝突検出など)が必要だと思います。決して起こらない状況をデバッグするのに私がどれだけの時間を費やしたかに驚くでしょう。
ニュートピア

1
私は自分自身を明確にしなかったと思います。より明確になるように回答を更新しました。
ピート

7

これは非常に良い質問です。あちこちでUUIDを使用することが急ぎで十分に考慮されているとは思わない。確かな研究は見つかりませんでした。

提案:ここでは非常に慎重に踏み、暗号化について十分に理解してください。128ビットUUIDを使用する場合、「誕生日効果」は、各キーに128ビットのエントロピーがある場合、約2 ^ 64キーを生成した後に衝突が発生する可能性があることを示しています

これが事実であることを確認するのは実際にはかなり困難です。真のランダム性は、(a)放射性崩壊(b)ランダムなバックグラウンド無線ノイズから生成される可能性があり、注意しない限りしばしば汚染される(c)適切に選択された電子ノイズ、たとえば逆バイアスツェナーダイオードから取得 (私は最後のもので遊んだことがあり、それは魅力のように機能します、ところで)。

ユーザーが2 ^ 64(つまり約10 ^ 19)に近いキーを生成し、それらすべてを相互にチェックしていない限り、「1年間の使用でこれを見たことがない」などの宣言を信用しません。自明でない運動。

問題はこれです。キーを他のすべてのキーと共通のキースペースで生成している他のすべてのキーと比較するとき、たった100ビットのエントロピーがあるとしましょう。約2 ^ 50で衝突が発生し始めます。約10 ^ 15個のキー。わずか1,000億のキーをデータベースに追加した場合に衝突が発生する可能性は、まだ無視できます。また、チェックしないと、ペタロウサイズのデータ​​ベースに忍び込む予期せぬエラーが後で発生します。これは激しく噛む可能性があります。

このようなUUIDを生成するためのアプローチが複数あるという事実は、一時的な不安を引き起こすはずです。タイプ4 UUIDに十分なエントロピーを持つ「真にランダムな」プロセスを使用するジェネレーターがほとんどないことに気付いた場合、ジェネレーターのエントロピーコンテンツを慎重に調べない限り、過度に心配する必要があります。(ほとんどの人はこれを実行せず、その方法も知らないでしょう; DieHarderスイートから始めるかもしれません)。擬似乱数生成と真の乱数生成を混同しないでください。

入力するエントロピーは自分が持っているエントロピーであることを理解することが重要であり、暗号化関数を適用してキーを摂動してもエントロピーは変更されません。私のスペース全体が数字の0と1で構成されている場合、エントロピーの内容は次の2つの文字列と同じであるということは直観的に明らかではないかもしれません。 !@@#&^%$$),. m}」と「そして今は完全に異なるもののために」。まだ2つのオプションがあります。

ランダムネスを正しく行うには注意が必要であり、単に「専門家はそれを見た、それで問題ない」と考えるだけでは十分ではないかもしれません。専門の暗号学者(そして、本当に熟練したこれらの人はほとんどいません)は、彼らがしばしば間違っていると認める最初の人です。ハートブリード、DigiNotarなどを信頼しました。

Paul Tomblinは適切な注意を払っていると思います。私の2c。


6

あなたが持っている問題は、「乱数発生器」を使用し、その発生器がどれほどランダムであるかわからない場合、衝突の確率は実際には不明であるということです。乱数ジェネレーターが何らかの方法で相関している場合、衝突の確率は劇的に増加する可能性があります-おそらく、多くのオーダーまたは大きさ。

衝突の確率が非常に小さい場合でも、根本的な問題があります。確率は0ではありません。これは、衝突が最終的に発生することを意味し、頻繁には発生しません。

UUIDを頻繁に生成して使用するほど、衝突が発生する可能性が高くなります。(1年に1を生成するということは、1秒あたり100万を生成するよりも長い待ち時間を意味し、他のすべての条件は同じです)。

その確率が有限で不明であり、多くのUUIDを使用する場合、衝突の結果を考慮する必要があります。例外をスローしてビジネスアプリケーションをシャットダウンすることが受け入れられない場合は、実行しないでください。(私の頭の上の例:「ライブラリチェックインの更新中にWebサーバーをシャットダウンしても構いません...頻繁に起こることはありません」と「給与計算システムをシャットダウンしても構いません。これらの決定は、キャリアを制限する動きかもしれません。)

ただし、アプリケーションによっては、さらに悪いケースもあります。UUIDの存在をテストし(つまり、ルックアップを実行し)、まだ存在しない場合は新しいものを作成します(これは、実行するのに十分な一般的なことです)。 、実際には、接続すべきでないUUIDを介して2つのものを接続している場合。これは、例外をスローしても何も解決せず、どこかで検出できない混乱が発生するものです。これは、情報漏えいにつながる種類のものであり、非常に恥ずかしいことがあります。(例:銀行にログインして、他の誰かの口座の残高を見ることができます!悪い!)

要約:UUIDの使用方法と衝突の結果を考慮する必要があります。これにより、衝突の検出と回避に注意を払うか、衝突が発生した場合に単純なアクションをとるか、何もしないかを決定します。単純な、単一の、すべてに適合するソリューションは、状況によっては不適切である可能性があります。


2
「(衝突の)確率は0ではありません」有限長のシーケンスにはこのプロパティがあります。でもと完全にあなたが2 ^ 122ユニークのUUID(128ビットマイナス4ビットバージョンマイナス2予約ビット)を生成したら、ランダムなv4のUUID、あなたが発生し、次のいずれかをされた保証衝突します。ほとんどの場合、それよりも早く衝突するでしょう。より大きな問題は、5e36繰り返しのようなものの後の衝突が問題であり、一般的に答えることができないかどうかです(ただし、特定のケースごとに答えることは明らかに可能ですが)。
CVn

もちろん。これは明らかなことの声明でした(しかし、まだ繰り返しがあります)。問題は、乱数ジェネレーターとの相関関係です。これにより、衝突の確率が大幅に増加する可能性があります(2 ^大きい)が、掘り出し、研究、または計算を多く行わない限り、どれだけ知らないかはわかりません。衝突の可能性が最良の値よりも著しく悪いと仮定すると、おそらく賢明です。その後...結果を考慮する必要があります。
すぐに今すぐ

0

関係する2つの問題があります。

  1. 使用される乱数ジェネレーターの品質。

  2. 生成される可能性のあるUUIDの量。

「ランダムな」UUIDには122個のランダムビットがあります。完全なランダム性を仮定すると、約2 ^ 61で生成されたUUID(2 ^ 122の平方根)での最初の衝突が予想されます。この地球上の誰もが1秒あたりのUUIDを生成する場合、それは10,000,000,000 * 365 * 24 * 60 * 60 = 315360000000000000 UUID /年であり、これは2 ^ 58に非常に近いです。つまり、数年後には最初の衝突が発生します。アプリケーションがこれらの数値の近くに到達しない限り、ランダムジェネレーターの品質が適切であれば衝突は発生しないと確信できます。

乱数ジェネレーターについて話す:標準のCライブラリジェネレーター(直接、間接、または同様のジェネレーター)を使用し、おそらくそれらに時間をシードすると、混乱します。これらは衝突を避けるのに十分なエントロピーを利用できません。ただし、Linuxを使用している場合は、から16バイトのデータを読み取るだけです/dev/urandom。これは、実際のランダムイベントにアクセスできるカーネルによって攪拌されるエントロピープールを使用します。通常、実際にUUIDを生成しない限り、本当にブートシーケンスの早い段階で、/dev/urandom真のランダムソースのように動作するはずです。


-1

1000万UUID-sを生成する非常に単純な(ブルートフォース)プログラムを使用して一度テストしましたが、衝突は発生していません。

UUID RFCは、 UUIDは、(擬似)乱数のちょうど束ではないと言います。


1
私が質問しているバージョン4は、ほとんどすべての乱数です。ただし、6ビットはすべて同じです。
ポールトムブリン

8
1,000万は、バケツの低下でさえありません。衝突の可能性は3E30分の1だけです。見つかった場合は、できるだけ多くの宝くじで急いでチケットを購入することをお勧めします。
ロスパターソン

@RossPatterson、私が特に気になっていたのは、同じハードウェアでまったく同じ擬似乱数アルゴリズムを使用している数百台のコンピューターがある場合、衝突の可能性が劇的に増加するということです。そうなると思う。
ポールトムブリン

1
@Paul-最初のシード処理プロセスでエントロピーが不十分な場合にのみ考えていました。たとえば、シードが時刻からのみ生成され、すべてのマシンが同じ瞬間に非常に近く起動した場合などです。シーディングがそれほど弱いことは非常に疑わしいです。ハードウェアのシリアル番号が使用されている可能性すらあり、これはもちろん各マシンに固有のものです。
Steve314

1
残念ながら、播種は非常に弱い場合があります。Linuxシステムは、非常にランダムなソース(デバイスドライバーのアクティビティなど)からPRNGをシードすることを好みますが、他の環境では、標準は現在のタイムスタンプを使用することです。
ロスパターソン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.