ハッシュ衝突とハッシュ衝突攻撃の分析

1. ハッシュ衝突とは何ですか?

ハッシュテーブルにデータを挿入すると、異なるキー値によって生成されたh(キー)は等しくなり、この時に競合が発生します。

2. ハッシュの競合を解決するにはどうすればよいですか?

一般的に使用される方法には、オープン アドレス指定方法、ジッパー方法、再ハッシュ方法、およびパブリック オーバーフロー領域の確立などがあります。

1. オープンアドレッシング方式

いわゆるオープン アドレッシング方法では、競合が発生した場合に次の空のハッシュ アドレスを見つけます。ハッシュ テーブルが十分に大きい限り、空のハッシュ アドレスは常に見つけることができ、レコードは式 fi( key) 
= (f(key)+di) MOD m (di=1,2,3,……,m-1)


詳細な説明: 競合が発生した場合、何らかの検出テクノロジーを使用してハッシュ テーブル内に検出シーケンスを形成します (シーケンスを生成するためのさまざまなルールに従って、線形検出方法、擬似ランダム検出方法、二次検出方法、ダブル ハッシュが使用できます)方法など)。指定されたキーワードが見つかるか、公開アドレスが見つかるまで (つまり、アドレス セルが空になるまで)、このシーケンスに沿ってセルごとに検索します。


たとえば (例を借用します)、キーワード セットは {12,67,56,16,25,37,22,29,15,47,48,34} で、テーブルの長さは 12 です。ハッシュ関数 f(key) = key mod l2 を使用します。 
最初の S 数値 {12, 67, 56, 16, 25} を計算するとき、それらはすべて競合のないハッシュ アドレスであり、直接保存されます。 

ここに画像の説明を書きます 
key = 37 を計算すると、f(37) = 1 であることがわかり、25 の位置と矛盾します。 
したがって、上記の式 f(37) = (f(37)+1) mod 12 = 2 を適用します。したがって、37 はインデックス 2 の場所に保存されます。 
ここに画像の説明を書きます

2. ジッパー方式

ジッパー メソッドは、ハッシュの競合を解決する効果的な方法です (たとえば、PHP と Java は、このメソッドを使用してハッシュの競合を解決します)。一部のハッシュ アドレスは、複数のキーワード値で共有できるため、各ハッシュをターゲットにすることができます。目的のアドレスのリスト。

原則: 各ハッシュ テーブル ノードにはネクスト ポインタがあります。複数のハッシュ テーブル ノードは、ネクスト ポインタを使用して一方向リンク リストを形成できます。同じインデックスに割り当てられた複数のノードは、この一方向リンク リストを使用して接続できます。

たとえば(例をお借りします):キーと値のペア k2, v2 とキーと値のペア k1, v1 の計算されたインデックス値は両方とも 2 です。 このとき競合が発生しますが、k2 と v1 が一致するノードは特定された k1 は次のポインタを介して接続できるため、ハッシュ競合の問題が解決されます。 
ここに画像の説明を書きます

3. リハッシュ法

リハッシュ法は比較的理解しやすいです。リハッシュ法はダブルハッシュ法とも呼ばれます。複数の異なるハッシュ関数があります。競合が発生した場合は、2 番目の関数を使用できます。競合が発生した場合は、引き続き 3 番目の関数を使用します。関数、ハッシュ方式は集計が行われにくいですが、計算時間が大幅に増加します。

4. 公共のオーバーフローエリアを確立する

原則: ハッシュ テーブルを基本テーブルとオーバーフロー テーブルの 2 つの部分に分割し、基本テーブルと競合する要素はすべてオーバーフロー テーブルに埋められます。

3. ハッシュ衝突を利用した攻撃

PHP や Java などの言語では、ハッシュの競合を解決するためにジッパー メソッドが使用されると上で述べました。

攻撃原理は、悪意のあるデータを作成してハッシュ テーブルをリンク リストに縮退させ、データが挿入されるたびにリンク リストを走査し、大量のサーバー リソースを消費することで攻撃の目的を達成します。

例: PHP 配列はハッシュ テーブルを使用して実装されます。例を使用して、悪意を持って構築されたデータと通常のデータの違いを見てみましょう。

    <?php
    $size = pow(2, 16);
    $startTime = microtime(true);
    $array = array();
    for ($key = 0, $maxKey = ($size - 1) * $size; $key <= $maxKey; $key += $size) {
        $array[$key] = 0;
    }
    $endTime = microtime(true);
    echo '插入 ', $size, ' 个恶意的元素需要 ', $endTime - $startTime, ' 秒', "\n";

    $startTime = microtime(true);
    $array = array();
    for ($key = 0, $maxKey = $size - 1; $key <= $maxKey; ++$key) {
        $array[$key] = 0;
    }
    $endTime = microtime(true);
    echo '插入 ', $size, ' 个普通元素需要 ', $endTime - $startTime, ' 秒', "\n";

上記の例では、悪意を持ってデータが構築され、データが書き込まれるたびにハッシュの競合が発生し、データが格納されるたびにリンク リスト全体が走査されます。私のマシンでの実行結果は次のとおりです。

(これは、私のマシン構成が上位であり、php7 でハッシュ テーブルの構造とアルゴリズムが最適化されているためです。php5.6 を使用すると、さらに時間がかかります)

插入 65536 个恶意的元素需要 7.9304070472717 秒
插入 65536 个普通元素需要 0.0048370361328125 秒

Niao Ge のブログアドレスを参照してください: PHP 配列のハッシュ競合例 - 風雪の片隅

おすすめ

転載: blog.csdn.net/panjiapengfly/article/details/121145250
おすすめ