3
<?php
function md7($text, $len)
{
  if($text)
  {
   $split = str_split(md5($text).md5(strlen($text)).md5($len), 5);
    foreach($split as $key=>$value)
    {
      $md5 = $md5.md5($value);
    }
    $split2 = str_split($md5);
    foreach($split2 as $kl=>$vl)
    {
      if($kl < $len)
      {
        $digest = $digest.$split2[$kl];
      }   
    }
    return $digest;
  }
} // end md7 function
?>

私は md5 と可変長ハッシュを利用するためにこの関数を作成しました。これにより衝突の可能性が減ると思います。MD5 衝突の例をテストしましたが、この関数の衝突は作成されません。この関数は私が信じていますレインボー テーブル攻撃の影響を受けません。

4

3 に答える 3

4

以下に、明らかなセキュリティ上の欠陥をいくつか示します。

if($text)

と の両方が同じハッシュ"0"を返します。""

foreach($split as $key=>$value)
{
  $md5 = $md5.md5($value);
}

最初のハッシュの個々の文字をハッシュしています。これにより$len <= 32、最初の文字が同じであるすべての文字列に対してまったく同じハッシュが得られるようになりmd5($value)、本質的にエントロピーが 128 ビットから 4 に減少します。$len = を使用した 16 個すべてのハッシュ値の完全なリストを次に示します。 32:

8f14e45fceea167a5a36dedd4bea2543
92eb5ffee6ae2fec3ad71c777531578f
a87ff679a2f3e71d9181a67b7542122c
e4da3b7fbbce2345d7772b0674a318d5
c81e728d9d4c2f636f067f89cc14862c
8277e0910d750195b448797616e091ad
0cc175b9c0f1b6a831c399e269772661
45c48cce2e2d7fbdea1afc51c7c6ad26
4a8a08f09d37b73795649038408b5f33
e1671797c52e15f763380b45e841ec32
eccbc87e4b5ce2fe28308fd9f2a7baf3
c4ca4238a0b923820dcc509a6f75849b
8fa14cdd754f91cc6554c9e71929cce7
c9f0f895fb98ab9159f51fd0297e236d
1679091c5a880faf6fb5e6087eb1b2dc
cfcd208495d565ef66e7dff9f98764da

を選択しても、この問題は軽減されないことに注意してください$len > 32。元のハッシュの 2 番目の文字のみを引き続き使用します。これにより、4 ビット多くのエントロピー (現在は最大 8 ビット) が得られ、256 の異なるハッシュに相当します。

元の md5 のエントロピーと一致させるには、32^32 の長さが必要であると確信しています。それはとてつもなく大きな数です。


セキュリティが必要な場合は、適切に定義され、十分にテストされたハッシュ関数を使用してください。PHP にはsha1関数だけでなく、ハッシュ関数に他の関数も多数あります。

ハッシュ関数は通常、暗号化コミュニティによって作成およびレビューされます。これらは、考えつくほとんどの単純なハックよりもはるかに優れているため、独自のハッシュ関数を実装せずに、利用可能な関数のいずれかを使用してください。

于 2012-10-13T06:14:42.550 に答える
3

""関数がおよびに対して何も返さないことに加えて"0"、最終的なハッシュ値は、16 進数文字0–<code>9 およびa–<code>f の MD5 ハッシュ値のみで構成されます。これらは次のとおりです。

string(32) "cfcd208495d565ef66e7dff9f98764da"
string(32) "c4ca4238a0b923820dcc509a6f75849b"
string(32) "c81e728d9d4c2f636f067f89cc14862c"
string(32) "eccbc87e4b5ce2fe28308fd9f2a7baf3"
string(32) "a87ff679a2f3e71d9181a67b7542122c"
string(32) "e4da3b7fbbce2345d7772b0674a318d5"
string(32) "1679091c5a880faf6fb5e6087eb1b2dc"
string(32) "8f14e45fceea167a5a36dedd4bea2543"
string(32) "c9f0f895fb98ab9159f51fd0297e236d"
string(32) "45c48cce2e2d7fbdea1afc51c7c6ad26"
string(32) "0cc175b9c0f1b6a831c399e269772661"
string(32) "92eb5ffee6ae2fec3ad71c777531578f"
string(32) "4a8a08f09d37b73795649038408b5f33"
string(32) "8277e0910d750195b448797616e091ad"
string(32) "e1671797c52e15f763380b45e841ec32"
string(32) "8fa14cdd754f91cc6554c9e71929cce7"

で同じものを使用する場合md7($c, 32):

NULL
string(32) "4a8a08f09d37b73795649038408b5f33"
string(32) "4a8a08f09d37b73795649038408b5f33"
string(32) "e1671797c52e15f763380b45e841ec32"
string(32) "0cc175b9c0f1b6a831c399e269772661"
string(32) "e1671797c52e15f763380b45e841ec32"
string(32) "c4ca4238a0b923820dcc509a6f75849b"
string(32) "c9f0f895fb98ab9159f51fd0297e236d"
string(32) "4a8a08f09d37b73795649038408b5f33"
string(32) "a87ff679a2f3e71d9181a67b7542122c"
string(32) "cfcd208495d565ef66e7dff9f98764da"
string(32) "45c48cce2e2d7fbdea1afc51c7c6ad26"
string(32) "a87ff679a2f3e71d9181a67b7542122c"
string(32) "c9f0f895fb98ab9159f51fd0297e236d"
string(32) "e1671797c52e15f763380b45e841ec32"
string(32) "c9f0f895fb98ab9159f51fd0297e236d"

繰り返しますが、 を0返しますNULL。しかし、もっと興味深いのは、{ 1, 2, 8}、{ 3, 5, 7}、および { c, f} の文字が同じハッシュ値になることです。これは、MD5 ハッシュ値が同じオクテットで始まるためです。これらのハッシュを使用して最終的な MD7 ハッシュを作成すると、結果のハッシュの最初の 32 文字の 16 進数も同じになります。

したがって、長さが 32 以下の場合、可能な MD7 ハッシュは 16 のみであり、長さが 64 以下の場合、2 つの MD7 ハッシュは 16 あります。最大長は 3・32・32=3072 であり、可能な MD7 ハッシュ値の数は 16 3・32です。

しかし、最後の 3072 文字の長さの MD7 ハッシュには 16^192 エントロピーがありません。最後の 1024 文字は、既知の結果の MD7 ハッシュの長さから派生するため、不明な文字は 2048 文字しか残っていません。

ハッシュ ループを逆にすることができるため、テキストとその長さの初期 MD5 を取得することもできます。

次に例を示します。

function md7_info($hash) {
    $hashlen = strlen($hash);

    $md5_to_hex = array();
    foreach (str_split('0123456789abcdef') as $c) $md5_to_hex[md5($c)] = $c;

    $md5_text = '';
    foreach (str_split(substr($hash, 0, 1024), 32) as $h) $md5_text .= $md5_to_hex[$h];

    $md5_textlen = '';
    foreach (str_split(substr($hash, 1024, 1024), 32) as $h) $md5_textlen .= $md5_to_hex[$h];

    return array($md5_text, $md5_textlen, $hashlen);
}

元のテキストの長さの MD5 を逆にすることもできます。最終的に残る情報は、MD5 とテキストの長さです。それほど多くのセキュリティは得られません。実際、テキストの長さを知ることで、実際に追加情報が明らかになります。

于 2012-10-13T07:23:58.793 に答える
1

ここで検討する価値のある問題がありますが、md5 ハッシュを簡単に分析する方法はありません。

これを 2 つの部分に分けて考えてみましょう。前半は入力を受け取り、それとその長さと戻り値の長さをハッシュします。文字列と連結された配列の効果がどうなるかはわかりませんが、インスタンスごとにコピーされただけだと仮定します。

次に、それぞれを反復処理して、新しい値を作成します: $md5 = $md5.md5($value). 最大 $len の文字列を返すことを考えると、文字列から最初の $len バイトを返すため、これが最大の弱点のようです。

いくつかの効果: $md5 は主に入力の開始に依存します。次のようなものを試してください

md7("aaaaaaaaaaaaaaaaaaaaaaaa", 16)
md7("aaaaaaaaaaaaaaaaaaaaaaab", 16)

同様の結果が得られるかどうかを確認します。私はこれを試していませんが、私の推測では、あなたが望むように入力全体を適切に混合していません。

于 2012-10-13T07:03:54.487 に答える