MD5ハッシュ値を元に戻せないのはなぜですか?


91

私がいつも疑問に思っている1つの概念は、暗号化ハッシュ関数と値の使用です。これらの関数は一意であり、事実上リバースすることは不可能であるハッシュ値を生成できることを理解していますが、これは私がいつも疑問に思っていたことです:

私のサーバー上にある場合、PHPで以下を生成します。

md5("stackoverflow.com") = "d0cc85b26f2ceb8714b978e07def4f6e"

MD5関数を介して同じ文字列を実行すると、PHPインストールで同じ結果が得られます。ある開始値から、ある値を生成するためにプロセスが使用されています。

これは、何が起こっているのかを分解してハッシュ値を逆にする方法があることを意味しませんか?

結果の文字列をたどることが不可能になるこれらの関数については何ですか?


54
たとえば、非可逆値の簡単な例はモジュロです。例えば10%3 = 1、それはまた、4とすることができるように、あなたは1〜10を元に戻すことはできません
甲ロイヤー

57
データを再構築できれば、これまでで最も効率的なロスレス圧縮アルゴリズムが得られます:)
Dan Diplo

回答:


204

入力素材は無限の長さにすることができ、出力は常に128ビット長です。これは、無限の数の入力文字列が同じ出力を生成することを意味します。

乱数を選び、それを2で割り、残りを書き留めると、それぞれ0または1-偶数または奇数-が得られます。その0または1を取り、元の番号を取得することは可能ですか?


4
つまり、数値->剰余も文字列-> md5も「単射関数」ではありません。
Federico A. Ramponi、2008

フェデリコ、確かにあなたはどちらも全単射関数ではないということですか?どちらも単射です。
Mihai Limbășan 2008

10
moocha:単射は1から1を意味します。ドメインが範囲よりも大きいため、MD5は確かに1から1ではありません。注目に値するもう1つの点は、MD5チェックサムを考えると、それにハッシュする文字列を1つでも見つけることは非常に難しいということです。明確にするために回答に追加する価値があるかもしれません。
biozinc 2008

4
一意の値を生成するハッシュ関数を持つことは不可能です。無限数の値を有限数の値にマッピングして、衝突を保証します。
Cody Brocious

4
あなたの答えは重要なポイントを扱っていないことをお勧めします。biozincが述べたように、安全なパスワードハッシュにとって重要なことは、出力を作成する入力を見つけることができないことであり、元の入力を見つけることができないということではありません。その点で、MD5は必ずしも安全であるとは限りません(en.wikipedia.org/wiki/MD5#Collision_vulnerabilities)。
マイクペリー

53

MD5などのハッシュ関数がリバーシブルである場合、それはデータ圧縮アルゴリズムの歴史における分岐点イベントでした。MD5がリバーシブルである場合、任意のサイズの任意のデータチャンクは、情報を失うことなく、わずか128ビットで表すことができることは簡単にわかります。したがって、元のメッセージのサイズに関係なく、128ビットの数値から元のメッセージを再構築できます。


9
代わりにmd5を入手できれば、Linuxディストリビューションをダウンロードするのがどれほど速くなるかを考えてみてください:)
Colin Pickard

15
@Colin Pickard:これ以上Linuxディストリビューションをダウンロードするのではなく、書き留めます。:)
tzot 2009年

29

ここで最もupvoted答えは強調して何に反して、非単射(すなわち、同じ値にハッシュする複数の文字列があること)違いによる暗号ハッシュ関数の大規模な(潜在的に無限の)入力サイズと固定出力サイズの間ではありません重要なポイント –実際には、これらの衝突ができる限り発生しないハッシュ関数を好みます。

この関数を考えてみてください(質問として、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のようなハッシュ関数とプリイメージ攻撃(単一ブロックのハッシュされた文字列を使用して物事を簡単にするため)の場合、暗号化関数の入力と出力だけがあり、キーはありません(これが探しているものです)。


4
はい、私はこれがかなり遅い答えであることを知っていますが、受け入れられた答えはこのように立ってはいけません。
パウロEbermann

私はあなたの批判にはいくつかのメリットがあると思いますが、実際の質問に答えることに失敗しました。あなたの答えは、暗号化ハッシュが持つべき品質に焦点を当てていますが、それらがmd5によってどのように実装されるかについての説明はありません。MD5サムを計算するための正確なアルゴリズムをここに記述して、それがどのように可逆的ではないかを示すことができますが、他の答えは、重要な点に踏み込むことなく、より簡単な説明を提供します。
Autodidact 2015年

(続き...)2.これらの説明では、「数学」を使用して、そのような操作によって情報が失われ、元に戻せなくなるという根本的な問題を示しています。
Autodidact 2015年

1
@SandeepDatta私はこれについていくつかの段落を追加しました。
–PaŭloEbermann、2015

1
このスレッドの他の答えはより技術的に正しいですが、この答えが最も役立ちます。非単射関数f(x)= 1は、元に戻すことはできませんが、興味がありません。それを見つけることは困難であるプレイメージ抵抗にあるハッシュの有用任意の特定の出力を生じる入力。
ジャスティンJスターク

18

Cody Brociousの答えは正しいものです。厳密に言えば、多くの文字列が同じハッシュにマッピングされるため、ハッシュ関数を「反転」することはできません。ただし、特定のハッシュにマッピングされる1つの文字列を見つけるか、同じハッシュにマッピングされる2つの文字列を見つける(つまり衝突)のどちらかが、暗号解読者にとって大きな進歩であることに注意してください。これらの両方の問題の大きな困難は、優れたハッシュ関数が暗号化に役立つ理由です。


12

MD5は一意のハッシュ値を作成しません。MD5の目標は、ソースの小さな変更に基づいて大幅に変化する値をすばやく生成することです。

例えば、

"hello" -> "1ab53"
"Hello" -> "993LB"
"ZR#!RELSIEKF" -> "1ab53"

(明らかに、これは実際のMD5暗号化ではありません)

ほとんどのハッシュ(すべてではないにしても)も一意ではありません。むしろ、それらは十分にユニークので、衝突はほとんどあり得ませんが、それでも可能です。


8

ハッシュアルゴリズムについて考える良い方法は、Photoshopで画像のサイズを変更することです... 5000x5000ピクセルの画像があり、それをちょうど32x32にサイズ変更するとします。あなたが持っているものは、まだ元の画像の表現ですが、はるかに小さく、画像データの特定の部分を効果的に「捨てて」、小さいサイズに収めています。したがって、32x32の画像のサイズを5000x5000に戻すと、ぼやけた混乱になります。ただし、32x32の画像はそれほど大きくないため、理論的には別の画像を縮小してまったく同じピクセルを生成できると考えられます。

これは単なる類推ですが、ハッシュの機能を理解するのに役立ちます。


3
画像のサイズ変更は不可逆なプロセスですが、元の5000×5000サイズで画像を生成することは非常に簡単です(縮小機能を再度適用すると)、同じ32×32の画像に縮小されます。そのようなプリイメージを見つけることは、良いハッシュ関数にとって難しいでしょう。
パウロEbermann

4

ハッシュの衝突は、あなたが考えるよりもはるかに可能性が高いです。それがなぜであるかについての理解を深めるために、誕生日のパラドックスを見てください。


1
365の可能な誕生日値があり、2 ^ 8と2 ^ 9の間です。128ビットのハッシュには2 ^ 128の可能な値があります-2 ^ 120倍です。はい、衝突はあなたが直感するよりも起こりそうですが、それらはまだ天文学的に起こりそうもありません。
Tim Keating

ハッシュの衝突が発生する可能性を高めるには、約2 ^ 64の異なる値が必要です。まだかなり。
パウロEbermann

4

可能な入力ファイルの数は128ビット出力の数よりも多いため、可能なそれぞれにMD5ハッシュを一意に割り当てることは不可能です。

暗号化ハッシュ関数は、データの整合性またはデジタル署名を確認するために使用されます(ハッシュは効率のために署名されています)。したがって、元のドキュメントを変更すると、元のハッシュが変更されたドキュメントと一致しなくなります。

これらの基準は時々使用されます:

  1. プリイメージ耐性:与えられたハッシュ関数と与えられたハッシュに対して、その関数に対して与えられたハッシュを持つ入力を見つけるのは難しいはずです。
  2. 2番目のプリイメージ耐性:与えられたハッシュ関数と入力に対して、同じハッシュを持つ2番目の異なる入力を見つけるのは難しいはずです。
  3. 衝突抵抗:特定の機能があるため、同じハッシュで2つの異なる入力を見つけることは困難です。

これらの基準は、特定のハッシュに一致するドキュメントを見つけにくくするために選択されます。それ以外の場合は、元のドキュメントをハッシュで一致したドキュメントに置き換えることにより、ドキュメントを偽造することができます。(置換が意味不明なものであっても、オリジナルを単に置換すると混乱が生じる可能性があります。)

数値3は数値2を意味します。

特にMD5に関しては、欠陥があることが示されています: MD5と他のハッシュ関数を壊す方法


2

しかし、これがレインボーテーブルの出番です。基本的には、個別にハッシュされた大量の値であり、結果はディスクに保存されます。次に、反転ビットは、非常に大きなテーブルでルックアップを実行するために「ただ」です。

明らかに、これはすべての可能な入力値のサブセットに対してのみ実行可能ですが、入力値の境界がわかっている場合は、それを計算できる可能性があります。


ああそう。私はハッシュテーブルに関するJeffの投稿(codinghorror.com/blog/archives/000949.html)を読んで楽しんでおり、このスレッドは概念の理解に役立ちました。
barfoon 2008


1

ほとんどの人がすでにMD5は可変長のデータストリームが固定長のデータチャンクにハッシュされるように設計されているため、1つのハッシュが多くの入力データストリームで共有されるとすでに述べています。

ただし、パスワードのハッシュがあり、元のパスワードを見つける必要がある場合など、チェックサムから元のデータを見つける必要がある場合は、ハッシュをグーグル(または任意の検索者)に検索する方が速いことがよくあります。強引に答えるよりも、答えのために。この方法でいくつかのパスワードを見つけました。


1

最も投票されたすべての回答が何を意味するかを理解する最良の方法は、実際にMD5アルゴリズムを元に戻そうとすることです。数年前にMD5cryptアルゴリズムを元に戻そうとしましたが、元のメッセージを回復するのは不可能でした。明らかに不可能であるので、元のハッシュと同じハッシュを生成するメッセージを生成するだけでした。これは、少なくとも理論的には、元のメッセージではなく、生成されたメッセージ(パスワード)を使用して/ etc / passwdファイルにuser:passwordを保存したLinuxデバイスにログインする方法を提供します。両方のメッセージのハッシュは同じであるため、システムは私のパスワード(元のハッシュから生成されたもの)を有効であると認識します。それはまったく機能しませんでした。数週間後、私が正しく覚えていれば、の使用最初のメッセージで私を殺した。有効な最初のメッセージだけでなく、ソルトされた有効な最初のメッセージを生成する必要がありました。しかし、この実験から得た知識は素晴らしかったです。


指定されたMD5ハッシュ値を合理的に効率的な方法で生成する入力を生成できた場合、それは暗号化コミュニティにとって大きな問題となり、公開する必要があります。これは、特定の入力がソルトされたかどうかとは完全に無関係です。
デイブL.17年

0

定義により、Hash(cryptographic Hash)関数:反転可能であってはなりません。

regdあなたの質問:それは一方向のハッシュです。inputは(長さに関係なく)固定サイズの出力を生成します(algo(MD5の場合は512ビット境界)に基づいてパディングされます)。情報は圧縮(損失)され、実際には逆変換から生成することはできません。

MD5に関する追加情報:衝突に対して脆弱です。最近この記事を読みました、 http://www.win.tue.nl/hashclash/Nostradamus/

暗号化ハッシュ実装(MD5およびSHA)のオープンソースコードは、Mozillaコードにあります。(freeblライブラリ)。


0

これで、MD5のハッシュやその他のハッシュは、すべての可能な文字列に対して事前に計算され、簡単にアクセスできるように保存されます。理論的にはMD5は可逆的ではありませんが、このようなデータベースを使用すると、特定のハッシュ値をもたらしたテキストを見つけることができます。

たとえば、http://gdataonline.com/seekhash.phpで次のハッシュコードを試して、ハッシュの計算に使用したテキストを確認してください。

aea23489ce3aa9b6406ebb28e0cda430

ああ、はい、ありふれた7文字の単語のハッシュです。それを使用して、空白と句読点を含むこの11ワードの歌詞を見つけます:9f2c08d4e6158bd4854b15be50c8daa8。数千年後にお会いしましょう。
Tim Keating

6fba2bbab8a8366309bf67c7df12c622?ヒント:Mac OS Xの特定のバージョンのOEMバージョンである可能性があります。
scherand 2010

@Tim Keating、@ scherand:ハッシュアルゴリズムの弱点を指摘するだけです。文字列のハッシュは常に同じであるため、実際の文字列を理解するために必ずしもアルゴリズムを解読する必要はありません。
Babarが2010

2
しかし、それはあなたが言ったことではありません。ハッシュは「可能なすべての文字列に対して事前に計算され、簡単にアクセスできるように保存される」と述べましたが、これは明らかに偽です(「すべての可能な文字列」のセットは無限です...そして「すべてのもっともらしい文字列」のセットでさえ、本当に、本当に大きいです)。私見これは、妥当なパスフレーズに対して辞書攻撃を行うのがいかに簡単かを誤って伝えています。
Tim Keating

0

f(x)= 1は元に戻せません。ハッシュ関数は元に戻せません。

これは、ハッシュされたデータの破損していないコピーを誰かが所有しているかどうかを判断する機能を実行するために実際に必要です。これにより、特にMD5に対して、最近非常に強力なブルートフォース攻撃を受けやすくなります。

数学の知識はあるが暗号解読の知識はほとんどない人々の間でも、ここや他の所で混乱があります。いくつかの暗号は、データとキーストリームを単純にXORします。したがって、任意のキーストリームを使用できたので、暗号文はその長さのすべての平文に対応すると言えます。

しかし、これは、シードから生成された合理的な平文が、シードpasswordによって生成された別の平文よりもはるかに可能性が高いことを無視Wsg5Nm^bkI4EgxUOhpAjTmTjO0F!VkWvysS6EEMsIJiTZcvsh@WI$IH$TYqiWvK!%&Ue&nk55ak%BX%9!NnG%32ftud%YkBO$U6oします。

同様に、2つの潜在的なパスワードをpasswordとの間で決定しようとしWsg5Nm^bkI4EgxUOている場合、一部の数学者があなたに信じさせるほど難しくはありません。


ほとんどの暗号は、データとキーストリームの知識のXORをどこで取得しますか?これはストリーム暗号にも当てはまりますが、ブロック暗号もあり、この方法では機能しません。
–PaŭloEbermann 2013

-5

私はさまざまな議論すべてが好きです。ハッシュ値の本当の価値は、パスワードなどの文字列に人間が読めないプレースホルダーを提供することだけであることは明らかです。特定の強化されたセキュリティ上の利点はありません。攻撃者がハッシュ化されたパスワードを使用してテーブルにアクセスしたとすると、次のことが可能になります。

  • 自分で選択したパスワードをハッシュし、テーブルへの書き込み/編集権限がある場合は、結果をパスワードテーブル内に配置します。
  • 一般的なパスワードのハッシュ値を生成し、パスワードテーブル内の類似したハッシュ値の存在をテストします。

この場合、弱いパスワードはハッシュされるという単なる事実では保護できません。


「ハッシュ値」の真の価値は、人間が読めないプレースホルダーを提供することではありません。「password1」が「newval」にハッシュされた場合、ハッシュは読み取り可能で意味がありますが、同じように値を非表示にしないのですか?さらに、パスワードはハッシュ化してはならないため、悪い例です。攻撃者が上記のデータベースへの書き込みアクセス権を持っていると想定すると、それは間違いなく可能性があります。ただし、そのようなハッシュ関数の適切な使用を単に破棄しているようです。1つの例は、上記の多くの回答で概説されています-メッセージの整合性。それが、今日私がこのスレッドに参加している理由です。
シェーン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.