web-dev-qa-db-ja.com

64ビットハッシュコードの衝突の確率

書籍NumericalRecipesは、衝突の数を減らすために64ビットハッシュコードを計算する方法を提供しています。

アルゴリズムは http://www.javamex.com/tutorials/collections/strong_hash_code_implementation_2.shtml に示され、参照用にここにコピーされます。

private static final createLookupTable() {
  byteTable = new long[256];
  long h = 0x544B2FBACAAF1684L;
  for (int i = 0; i < 256; i++) {
    for (int j = 0; j < 31; j++) {
      h = (h >>> 7) ^ h;
      h = (h << 11) ^ h;
      h = (h >>> 10) ^ h;
    }
    byteTable[i] = h;
  }
  return byteTable;
}

public static long hash(CharSequence cs) {
  long h = HSTART;
  final long hmult = HMULT;
  final long[] ht = byteTable;
  final int len = cs.length();
  for (int i = 0; i < len; i++) {
    char ch = cs.charAt(i);
    h = (h * hmult) ^ ht[ch & 0xff];
    h = (h * hmult) ^ ht[(ch >>> 8) & 0xff];
  }
  return h;
}

私の質問:

1)いわゆるバースデーパラドックスを考慮して衝突の確率を推定する式はありますか?

2)衝突の確率(つまり、同じ値にハッシュされる2つのキー)を見積もることができますか? 1,000個のキーと10,000個のキーがあるとしましょう。

[〜#〜]編集[〜#〜]:言い換え/修正された質問3

3)妥当な数のキー(たとえば、10,000キー未満)の衝突は非常に起こりそうにないので、2つのハッシュコードが同じである場合、それ以上チェックしなくてもキーは同じであると言えますか?例えば.

static boolean equals(key1, key2) {

  if (key1.hash64() == key2.hash64())
    return true;  // probability of collision so low we don't need further check

  return false;
}

これはセキュリティのためではありませんが、実行速度が不可欠であるため、キーのそれ以上のチェックを回避すると時間を節約できます。確率が非常に低い場合、たとえば(100,000キーに対して10億分の1)未満の場合は、おそらく許容されます。

TIA!

13
isapir

いわゆるバースデーパラドックスを考慮して衝突の確率を推定する式はありますか?

誕生日のパラドックスの式を使用すると、衝突が発生することを心配し始める必要がある時点がわかります。これは約_Sqrt[n]_にあります。ここで、nは可能なハッシュ値の総数です。この場合、_n = 2^64_であるため、Birthday Paradoxの式は、キーの数が_Sqrt[n] = Sqrt[2^64] = 2^32_または約40億よりも大幅に少ない限り、衝突について心配する必要がないことを示しています。 nが高いほど、この推定はより正確になります。実際、kキーとの衝突が発生する確率p(k)は、nが大きくなるにつれてステップ関数に近づき、ステップは_k=Sqrt[n]_で発生します。


衝突の確率(つまり、同じ値にハッシュされる2つのキー)を見積もることができますか? 1,000個のキーと10,000個のキーがあるとしましょう。

ハッシュ関数が均一に分布していると仮定すると、式を導出するのは簡単です。

_p(no collision for k keys) = 1 * (n-1)/n * (n-2)/n * (n-3)/n * ... * (n-(k-1))/n
_

この式は、1つのキーから直接実行されます。1つのキーとの衝突がない確率はもちろん1です。2つのキーとの衝突がない確率は1 * (n-1)/nです。すべてのkキーについても同様です。便利なことに、Mathematicaにはこれを簡潔に表現するための Pochhammer [] 関数があります。

_p(no collision for k keys) = Pochhammer[n-(k-1),k]/n^k
_

次に、kキーに対して少なくとも1つの衝突がある確率を計算するには、1からそれを引きます。

_p(k) = 1 - p(no collision for k keys) = 1 - Pochhammer[n-(k-1),k]/n^k
_

Mathematicaを使って、_n=2^64_を計算することができます:

  • p(1,000)= 3.7 * 10のうち113
  • p(10,000)= 3.7 * 10のうち111
  • p(1,000,0 3.7 * 10のうち17)==

妥当な数のキー(たとえば、10,000キー未満)の衝突は非常に起こりそうにないので、2つのハッシュコードが同じである場合、それ以上チェックしなくてもキーは同じであると言えると考えるのは安全ですか?

これに正確に答えるには、10,000個のキーのうち2個が同一である確率に依存します。私たちが探しているのは:

_p(a=b|h(a)=h(b)) = The probability that a=b given h(a)=h(b)
_

ここで、abはキー(おそらく同一)であり、h()はハッシュ関数です。 ベイズの定理 を直接適用できます:

_p(a=b|h(a)=h(b)) = p(h(a)=h(b)|a=b) * p(a=b) / p(h(a)=h(b))
_

p(h(a)=h(b)|a=b) = 1(_a=b_の場合はもちろんh(a)=h(b))であることがすぐにわかります。

_p(a=b|h(a)=h(b)) = p(a=b) / p(h(a)=h(b))
_

ご覧のとおり、これはp(a=b)に依存します。これは、abが実際に同じキーである確率です。これは、最初に10,000個のキーのグループがどのように選択されたかによって異なります。前の2つの質問の計算では、すべてのキーが異なることを前提としているため、完全に回答するには、このシナリオに関する詳細情報が必要です。

37
Matt

1)いわゆるバースデーパラドックスを考慮して衝突の確率を推定する式はありますか?

単一の衝突が発生する確率は、ハッシュ関数が均一であるために生成されたキーセットによって異なります。次のように、k個のキーの生成時に衝突が発生しない確率を計算できます。

_x = hash size
p(k=2) = (x-1)/x
p(k=3) = p(k=2)*(x-2)/x
..
p(k=n) = (x-1)*(x-2)..(x-n+1)/x^n

p(k=n) ~ e^-(n*n)/2x

p(collision|k=n) = 1-p(k=n) = 1 - e^(-n^2)/2x
p(collision) > 0.5 if n ~ sqrt(x)
_

したがって、_2^32_キーであるsqrt(2^64)キーが生成された場合、単一の衝突が発生する可能性が高くなります。

2)衝突の確率(つまり、同じ値にハッシュされる2つのキー)を見積もることができますか? 1,000個のキーと10,000個のキーがあるとしましょう。

_x = 2^64 
Use the formula pc(k=n) = 1 - e^-(n^2)/2x
_

3)妥当な数のキー(たとえば、10,000キー未満)の衝突は非常に起こりそうにないので、2つのハッシュコードが同じである場合、それ以上チェックしなくてもキーは同じであると言えますか?

これは、キースペースのサイズに依存するため、非常に興味深い質問です。先ほど述べたように、キーが_size = s_のスペースからランダムに生成され、ハッシュスペースが_x=2^64_であるとします。衝突の確率はPc(k=n|x) = 1-e^(-n^2)/2xです。キースペースで同じキーを選択する確率がP(k=n|s) = 1-e^(-n^2)/2sの場合。ハッシュが同じである場合、キーが同じであることを確認するために:-

_P(k=n|s) > Pc(k=n|x)
1-e^-(n^2/2s) > 1-e^-(n^2/2x) 
n^2/2s > n^2/2x 
s < x
s < 2^64
_

したがって、ハッシュが同じである場合にキーが同じであるためには、キーセットのサイズがおよそ_2^64_より小さくなければならないことを示しています。そうでない場合、キーセットよりもハッシュで衝突する可能性があります。結果は、生成されるキーの数とは無関係です。

1
Vikram Bhat

他の回答で提供されている正確な式の大まかな概算を提供します。近似はあなたが#3に答えるのを助けることができるかもしれません。大まかな概算では、k << nの場合、k個のキーとn個の可能なハッシュ値で適切なハッシュアルゴリズムを使用して衝突が発生する確率は約(k ^ 2)/ 2nです。 64ビットハッシュを使用する100,000キーの場合、10 ^ 10/32x10 ^ 18、つまり30億分の1になります。

ただし、衝突時に実際のキー値をチェックしないと、結局のところ、ハッシュアルゴリズムが十分に「適切」ではないことがわかる可能性が高くなると思います。

1
Warren Dew

いわゆるバースデーパラドックスを考慮して衝突の確率を推定する式はありますか?

参照: 誕生日攻撃

ハッシュの分布が均一であると仮定すると、nキーの衝突の確率は約nです。2/ 265

妥当な数のキー(たとえば、10,000キー未満)の衝突は非常に起こりそうにないので、2つのハッシュコードが異なる場合、それ以上チェックしなくてもキーが異なると言えると考えるのは安全ですか?

暗号化ハッシュ関数を使用する場合にのみ安全です。 3 * 10ごとに間違いを許容できるとしても11 プログラムへの攻撃として、入力がハッシュ衝突を作成するために特別に構築されている可能性を考慮する必要がある場合があります。

1
Anton