10

.NET で関数をコーディングして、シードに基づいて GUID を生成し、その一意性についてより信頼できるようにする最も簡単な方法は何ですか?

string GenerateSeededGuid(int seed) { /* code here */ }

理想的には、シードは次のように乱数生成を記述するCryptGenRandomから取得されます。

この関数によって生成されるデータは、暗号的にランダムです。これは、C コンパイラに同梱されている乱数ジェネレータなどの一般的な乱数ジェネレータによって生成されるデータよりもはるかにランダムです。

この関数は、ランダムな初期化ベクトルソルト値を生成するためによく使用されます。

ソフトウェア乱数ジェネレーターは、基本的に同じように機能します。シードと呼ばれる乱数から開始し、アルゴリズムを使用してそれに基づいてビットの疑似乱数シーケンスを生成します。このプロセスの最も難しい部分は、真にランダムなシードを取得することです。これは通常、ユーザー入力の遅延、または 1 つ以上のハードウェア コンポーネントからのジッターに基づいています。

Microsoft CSP では、CryptGenRandomは、他のセキュリティ コンポーネントで使用されるのと同じ乱数ジェネレーターを使用します。これにより、多数のプロセスがシステム全体のシードに貢献できます。CryptoAPI は、すべてのユーザーに中間ランダム シードを格納します。乱数ジェネレーターのシードを形成するために、呼び出し元のアプリケーションは、マウスやキーボードのタイミング入力などのビットを提供し、保存されているシードとさまざまなシステム データおよびプロセス ID などのユーザー データと組み合わせます。スレッド ID、システム クロック、システム時刻、システム カウンター、メモリ ステータス、空きディスク クラスター、ハッシュされたユーザー環境ブロック。この結果は、疑似乱数ジェネレーター (PRNG) のシードに使用されます。[...] アプリケーションが適切なランダム ソースにアクセスできる場合、CryptGenRandomを呼び出す前に、いくつかのランダム データを含む pbBufferバッファー。次に、CSP はこのデータを使用して、内部シードをさらにランダム化します。CryptGenRandomを呼び出す前にpbBufferバッファを初期化するステップを省略しても かまいません。

4

4 に答える 4

21

tldr; Guid.NewGuid別の「よりランダムな」アプローチを発明しようとする代わりに使用してください。(シードから UUIDvX を作成する唯一の理由は、予測可能で再設定可能なシーケンスが必要な場合です。ただし、GUID も最善の方法ではない可能性があります2。)

有限範囲であることのまさに定義によれば、128ビットからバージョン管理ビット 6を差し引いた、v4 の一意性は 122 ビットです。非常に多くの(とはいえ、非常に膨大な数! 天文学的に大きい! ) 「一意の」識別子があります。

ピジョンホールの原理により、ピジョンホールの数は非常に多くなります。ハトが最終的に繁殖し続けると、各ハトに十分な穴がなくなります。誕生日のパラドックスにより、完全にランダムであると仮定すると、2 匹のピジョンが同じピジョンホールをめぐって戦おうとします。Master Pigeonhole List 1がないため、これを防ぐことはできません。また、すべての動物がハトであるとは限りません3

どのGUID ジェネレーターが使用されるについての保証はありませんが、.NET は、 Windows 2k 以降の GUIDv4 (別名Random UUID ) ジェネレーターである基になる OS 呼び出しを使用します。私が知る限り、または実際に気にする限り、これはそのような目的のために得られるのと同じくらい良いランダムです. 10年以上にわたって十分に吟味されており、交換されていません。


ウィキペディアから:

.. 次の 100 年間、毎秒 10 億個の UUID を生成した後で初めて、複製が 1 つだけ作成される確率は約 50% になります。地球上のすべての人が 6 億の UUID を所有している場合、1 つの重複の確率は約 50% になります。

1ピジョンホールの有限セットがまだありますが、UUIDv1(別名MAC UUID)-一意の時間空間を想定-は、決定論的に一意の数値を生成することが保証されています(特定のマシンで1秒あたりに生成されるUUIDの「比較的小さい」理論上の最大数を使用) )。異なる平行次元に住む異なるハトの群れ - すごい!

2 Twitter は、Snowflakesを独自の分散型 Unique-ID スキームで並列次元で使用します。

3うさぎはピジョンホールではなく、巣穴に住むのが好きです。GUID を使用すると、暗黙的な並列パーティションとしても機能します。競合に関連する問題が発生する可能性があるのは、重複した GUID が同じ目的で使用された場合のみです。重複する自動インクリメント データベースのプライマリ キーの数を考えてみてください。

于 2012-11-02T03:18:34.697 に答える
18

メソッドで実際に行う必要があるGenerateSeededGuidのは、128 ビットの乱数を作成し、それを Guid に変換することだけです。何かのようなもの:

public Guid GenerateSeededGuid(int seed)
{
  var r = new Random(seed);
  var guid = new byte[16];
  r.NextBytes(guid);

  return new Guid(guid);
}
于 2012-11-02T02:22:27.947 に答える