バイナリアセットごとに、MD5ハッシュを生成します。これは、特定のバイナリアセットがすでにアプリケーションに存在するかどうかを確認するために使用されます。しかし、2つの異なるバイナリアセットが同じMD5ハッシュを生成する可能性があります。では、2つの異なる文字列が同じMD5ハッシュを生成する可能性はありますか?
バイナリアセットごとに、MD5ハッシュを生成します。これは、特定のバイナリアセットがすでにアプリケーションに存在するかどうかを確認するために使用されます。しかし、2つの異なるバイナリアセットが同じMD5ハッシュを生成する可能性があります。では、2つの異なる文字列が同じMD5ハッシュを生成する可能性はありますか?
回答:
何十億もの資産のセットの場合、ランダムな衝突の可能性は無視できるほど小さく、心配する必要はありません。誕生日のパラドックスを考えると、2 ^ 64(または18,446,744,073,709,551,616)アセットのセットが与えられた場合、このセット内での単一の MD5衝突の確率は50%です。この規模では、ストレージ容量の点でおそらくGoogleに勝るでしょう。
ただし、MD5ハッシュ関数が破損しているため(衝突攻撃に対して脆弱です)、攻撃者は、数秒のCPUパワーで2つの衝突するアセットを生成できます。したがって、MD5を使用する場合は、そのような攻撃者がアプリケーションのセキュリティを危険にさらさないようにしてください。
また、攻撃者がデータベース内の既存のアセットへの衝突を偽造する可能性がある場合の影響についても検討してください。MD5に対するそのような既知の攻撃(プリイメージ攻撃)はありませんが(2011年現在)、衝突攻撃に関する現在の研究を拡張することで可能になる可能性があります。
これらが問題であることが判明した場合は、SHA-2シリーズのハッシュ関数(SHA-256、SHA-384、SHA-512)を確認することをお勧めします。欠点は、少し遅くなり、ハッシュ出力が長くなることです。
はい、もちろんです。MD5ハッシュの長さは有限ですが、MD5ハッシュ化できる文字列は無限にあります。
はい、2つの異なる文字列が同じMD5ハッシュコードを生成する可能性があります。
16進文字列の非常に類似したバイナリメッセージを使用した簡単なテストを次に示します。
$ echo '4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa200a8284bf36e8e4b55b35f427593d849676da0d1555d8360fb5f07fea2' | xxd -r -p | tee >/dev/null >(md5) >(sha1sum)
c6b384c4968b28812b676b49d40c09f8af4ed4cc -
008ee33a9d58b51cfeb425b0959121c9
$ echo '4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa202a8284bf36e8e4b55b35f427593d849676da0d1d55d8360fb5f07fea2' | xxd -r -p | tee >/dev/null >(md5) >(sha1sum)
c728d8d93091e9c7b87b43d9e33829379231d7ca -
008ee33a9d58b51cfeb425b0959121c9
異なるSHA-1サムを生成しますが、MD5ハッシュ値は同じです。次に、文字列は非常に似ているため、それらの違いを見つけるのは困難です。
違いは次のコマンドで確認できます。
$ diff -u <(echo 4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa200a8284bf36e8e4b55b35f427593d849676da0d1555d8360fb5f07fea2 | fold -w2) <(echo 4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa202a8284bf36e8e4b55b35f427593d849676da0d1d55d8360fb5f07fea2 | fold -w2)
--- /dev/fd/63 2016-02-05 12:55:04.000000000 +0000
+++ /dev/fd/62 2016-02-05 12:55:04.000000000 +0000
@@ -33,7 +33,7 @@
af
bf
a2
-00
+02
a8
28
4b
@@ -53,7 +53,7 @@
6d
a0
d1
-55
+d5
5d
83
60
上記の衝突の例は、Marc Stevens によるものです。MD5、2012の単一ブロック衝突。彼は、ソースコード(論文への代替リンク)を使用して自分の方法を説明しています。
別のテスト:
$ echo '0e306561559aa787d00bc6f70bbdfe3404cf03659e704f8534c00ffb659c4c8740cc942feb2da115a3f4155cbb8607497386656d7d1f34a42059d78f5a8dd1ef' | xxd -r -p | tee >/dev/null >(md5) >(sha1sum)
756f3044edf52611a51a8fa7ec8f95e273f21f82 -
cee9a457e790cf20d4bdaa6d69f01e41
$ echo '0e306561559aa787d00bc6f70bbdfe3404cf03659e744f8534c00ffb659c4c8740cc942feb2da115a3f415dcbb8607497386656d7d1f34a42059d78f5a8dd1ef' | xxd -r -p | tee >/dev/null >(md5) >(sha1sum)
6d5294e385f50c12745a4d901285ddbffd3842cb -
cee9a457e790cf20d4bdaa6d69f01e41
異なるSHA-1合計、同じMD5ハッシュ。
違いは1バイトです。
$ diff -u <(echo 0e306561559aa787d00bc6f70bbdfe3404cf03659e704f8534c00ffb659c4c8740cc942feb2da115a3f4155cbb8607497386656d7d1f34a42059d78f5a8dd1ef | fold -w2) <(echo 0e306561559aa787d00bc6f70bbdfe3404cf03659e744f8534c00ffb659c4c8740cc942feb2da115a3f415dcbb8607497386656d7d1f34a42059d78f5a8dd1ef | fold -w2)
--- /dev/fd/63 2016-02-05 12:56:43.000000000 +0000
+++ /dev/fd/62 2016-02-05 12:56:43.000000000 +0000
@@ -19,7 +19,7 @@
03
65
9e
-70
+74
4f
85
34
@@ -41,7 +41,7 @@
a3
f4
15
-5c
+dc
bb
86
07
上記の例は、Tao XieとDengguo Feng:Construct a MD5 Collisions Using Just A Single Block of Message、2010を基にしています。
関連:
もっと情報を提供するだけです。数学の観点から見ると、ハッシュ関数は単射的ではありません。
これは、開始セットと結果のセットの間に1対1(ただし、一方向)の関係がないことを意味します。
編集:完全な単射ハッシュ関数が存在するために:それはパーフェクトハッシュと呼ばれています。
他の人が言ったように、はい、2つの異なる入力の間で衝突が発生する可能性があります。しかし、あなたのユースケースでは、それが問題であるとは思いません。あなたが衝突に遭遇することを強く疑います-私は以前のジョブで多数の画像(JPG、ビットマップ、PNG、raw)形式の数十万の画像ファイルのフィンガープリントにMD5を使用しましたが、衝突はありませんでした。
ただし、ある種のデータをフィンガープリントしようとしている場合、おそらく2つのハッシュアルゴリズムを使用できます。1つの入力が2つの異なるアルゴリズムの同じ出力になる可能性はほぼ不可能です。
これは古いことに気づきましたが、私の解決策に貢献したいと思いました。2 ^ 128の可能なハッシュの組み合わせがあります。したがって、誕生日のパラドックスの確率は2 ^ 64です。以下の解決策は衝突の可能性を排除するものではありませんが、リスクを大幅に削減します。
2^64 = 18,446,744,073,709,500,000 possible combinations
私がやったことは、入力文字列に基づいていくつかのハッシュを組み合わせて、ハッシュと見なすはるかに長い結果の文字列を取得することです...
したがって、これに対する私の擬似コードは次のとおりです。
Result = Hash(string) & Hash(Reverse(string)) & Hash(Length(string))
それは、衝突が実際に起こりそうにないことです。しかし、あなたが超偏執狂になりたくてそれを実現することができないなら、そしてストレージスペースは問題ではありません(計算サイクルでもありません)...
Result = Hash(string) & Hash(Reverse(string)) & Hash(Length(string))
& Hash(Reverse(SpellOutLengthWithWords(Length(string))))
& Hash(Rotate13(string)) Hash(Hash(string)) & Hash(Reverse(Hash(string)))
わかりました。最もクリーンなソリューションではありませんが、これにより、衝突に遭遇する頻度が非常に低くなるため、より多くの遊びが得られます。要するに、私は用語のすべての現実的な意味で不可能を仮定するかもしれません。
私にとっては、衝突の可能性は非常に低いので、これを「確実な」ものではないと考えますが、必要に応じて起こる可能性は低いと思います。
現在、可能な組み合わせは大幅に増えています。あなたはこれがあなたを得ることができる組み合わせの数に長い時間を費やすことができますが、私は理論的には上記の引用された数よりもかなり多くあなたを着陸させると言います
2^64 (or 18,446,744,073,709,551,616)
おそらく100桁以上増えるでしょう。これにより得られる理論上の最大値は
結果の文字列の可能な数:
528294531135665246352339784916516606518847326036121522127960709026673902556724859474417255887657187894674394993257128678882347559502685537250538978462939576908386683999005084168731517676426441053024232908211188404148028292751561738838396898767036476489538580897737998336
ハッシュの衝突は予想したほどまれではないので、要件に従ってハッシュアルゴリズムを慎重に選択する必要があると思います。最近、プロジェクトで非常に単純なハッシュ衝突のケースを見つけました。ハッシュにはxxhashのPythonラッパーを使用しています。リンク:https : //github.com/ewencp/pyhashxx
s1 = 'mdsAnalysisResult105588'
s2 = 'mdsAlertCompleteResult360224'
pyhashxx.hashxx(s1) # Out: 2535747266
pyhashxx.hashxx(s2) # Out: 2535747266
それはシステムで非常にトリッキーなキャッシング問題を引き起こし、それから私は最終的にそれがハッシュ衝突であることがわかりました。