ここで最も支持された回答が強調していることとは反対に、大きな(潜在的に無限の)入力サイズと固定出力サイズの違いによって引き起こされる暗号化ハッシュ関数の非単射性(つまり、同じ値にハッシュする複数の文字列があること)はそうではありません重要な点は、実際には、これらの衝突ができるだけ発生しないハッシュ関数を好むということです。
この関数を考えてみましょう(PHP表記で、質問として):
function simple_hash($input) {
return bin2hex(substr(str_pad($input, 16), 0, 16));
}
これにより、文字列が短すぎる場合にいくつかのスペースが追加され、文字列の最初の 16 バイトが取得され、16 進数としてエンコードされます。MD5 ハッシュと同じ出力サイズです (32 の 16 進文字、または bin2hex 部分を省略した場合は 16 バイト)。
print simple_hash("stackoverflow.com");
これは出力されます:
737461636b6f766572666c6f772e636f6d
この関数には、MD5 に対する Cody の回答で強調されているのと同じ非単射性プロパティもあります。任意のサイズの文字列を渡すことができ (コンピューターに収まる限り)、32 桁の 16 進数のみを出力します。もちろん、それは注射ではありません。
しかし、この場合、同じハッシュにマップする文字列を見つけるのは簡単です (ハッシュに適用するだけhex2bin
で、それが得られます)。元の文字列の長さが (この例のように) 16 の場合、この元の文字列も取得されます。MD5 では、入力の長さが非常に短いことがわかっている場合でも、このようなことはできません (ブルート フォース攻撃など、一致するものが見つかるまで可能なすべての入力を試す以外に)。
暗号化ハッシュ関数の重要な仮定は次のとおりです。
- 特定のハッシュを生成する文字列を見つけるのは難しい (プリイメージ耐性)
- 特定の文字列と同じハッシュを生成する別の文字列を見つけるのは難しい (2 番目のプリイメージ耐性)
- 同じハッシュを持つ文字列のペアを見つけるのは難しい (衝突耐性)
明らかに、私のsimple_hash
機能はこれらの条件のどちらも満たしていません。(実際には、入力スペースを「16 バイトの文字列」に制限すると、関数は単射になり、証明可能な 2 番目のプリイメージ耐性と衝突耐性さえあります。)
現在、MD5 に対する衝突攻撃が存在します (たとえば、与えられた同じプレフィックスを使用しても、同じハッシュを持つ文字列のペアを生成することが可能です。かなりの作業が必要ですが、多くの作業は不可能ではありません)。重要な場合は MD5。プリイメージ攻撃はまだありませんが、攻撃は良くなります。
実際の質問に答えるには:
これらの関数について、結果の文字列をたどることができないのはなぜですか?
MD5 (および Merkle-Damgard 構造に基づいて構築された他のハッシュ関数) が効果的に行うことは、メッセージをキーとして、固定値を「プレーン テキスト」として、結果の暗号文をハッシュとして使用する暗号化アルゴリズムを適用することです。(その前に、入力はパディングされ、ブロックに分割されます。このブロックのそれぞれは、前のブロックの出力を暗号化するために使用され、逆計算を防ぐためにその入力と XOR 演算されます。)
最新の暗号化アルゴリズム (ハッシュ関数で使用されるものを含む) は、平文と暗号文の両方が与えられたとしても (または敵がそれらのいずれかを選択したとしても)、キーを回復するのが困難になるように作られています。これは一般に、各出力ビットが各キー ビット (数回) と各入力ビットによって決定されるように、多くのビット シャッフル操作を行うことによって行われます。そうすれば、完全なキーと入力または出力のいずれかを知っている場合にのみ、内部で何が起こっているかを簡単にたどることができます。
MD5 のようなハッシュ関数とプリイメージ攻撃 (物事を簡単にするために単一ブロックのハッシュ文字列を使用) の場合、暗号化関数の入力と出力のみがあり、キーはありません (これが探しているものです)。