私はmd5ハッシュに関するウィキペディアの記事を読みましたが、ハッシュを元のテキストに「再構成」する方法を理解できません。
これがどのように機能するかについて、暗号についてほとんど知らない人に誰かが説明できますか?関数のどの部分が一方向にするのですか?
今まで誰もが単純にハッシュ関数とは何かを定義してきたので、私はかみます。
一方向関数は、ハッシュ関数(情報を失う関数)だけではなく、画像f
(「SE」または既存の回答では294)が指定された関数y
です)、f(x)=y
のようなプリイメージxを見つけるのは困難です。
これが一方向と呼ばれる理由です。画像を計算することはできますが、特定の画像のプレ画像を見つけることができません。
既存の回答でこれまで提案されていた通常のハッシュ関数には、この特性はありません。これらはいずれも一方向暗号ハッシュ関数ではありません。たとえば、 "SE"を指定すると、X-encode( "SXXXE")= SEというプロパティを持つ入力 "SXXXE"を簡単に取得できます。
「単純な」一方向関数はありません。彼らは入力をよく混ぜる必要があるので、出力で入力をまったく認識できないだけでなく、しかし別の入力を認識できませんどちらか。
SHA-1とMD5は以前は一方向の機能として一般的でしたが、どちらもほとんど機能していません(スペシャリストは、特定の画像のプレ画像を作成する方法を知っているか、またはほぼ作成できます)。 SHA- という名前の新しい標準のものを選択するコンテストが進行中です。
一方向関数を反転させる明らかなアプローチは、多くの画像を計算し、それを生成した事前画像を各画像に関連付けるテーブルに保持することです。これを実際に不可能にするために、すべての一方向関数は、少なくとも64ビットの大きな出力を持っていますが、おそらくそれよりもはるかに大きい(たとえば、512ビットまで)。
編集:ほとんどの暗号化ハッシュ関数はどのように機能しますか?
通常、それらのコアには、ビットのブロックに対して複雑な変換を行う単一の関数があります(a block cipher )。関数はほぼ全単射である必要があります(同じ画像にあまり多くのシーケンスをマッピングしないでください。後で弱点が生じるためです)。正確に全単射である必要はありません。そして、この関数は、入力(または可能な入力)を認識不能にするのに十分な、固定された回数繰り返されます。
SHA-3コンテキストの有力な候補の1つである Skein の例を見てみましょう。そのコア関数は72回繰り返されます。関数の作成者が出力を一部の入力に関連付ける方法を知っている唯一の反復回数は25です。彼らは、2.9の「安全率」があると言っています。
本当に基本的なハッシュを考えてみてください-入力文字列に対して、各文字のASCII値の合計を返します。
hash( 'abc' ) = ascii('a')+ascii('b')+ascii('c')
= 97 + 98 + 99
= 294
ここで、ハッシュ値が294である場合、元の文字列が何であったかわかりますか? 'abc'と 'cba'(そして無数の他のもの)が同じハッシュ値を与えるため、明らかにそうではありません。
アルゴリズムがはるかに複雑であることを除いて、暗号化ハッシュ関数は同じように機能します。常に衝突が発生しますが、文字列s
ハッシュからh
へのハッシュを知っている場合、construct anotherにするのは非常に困難( "計算不可能")です。 h
にもハッシュされる文字列。
ここでは、複雑な説明ではなく、単純な例えのために撮影しています。
まず、件名を一方向の操作とハッシュの2つの部分に分けましょう。一方向の操作とは何ですか。なぜ必要なのですか。
一方向の操作は、元に戻せないために呼び出されます。加算や乗算などの最も一般的な演算は逆にできますが、モジュロ除算は元に戻せません。なぜそれが重要なのですか?なぜなら、1)元の入力なしでは複製が困難であり、2)出力から入力を理解する方法が提供されない出力値を提供したいからです。
追加:
4 + 3 = 7
これは、合計を取り、加数の1つを差し引くことで元に戻すことができます
7 - 3 = 4
乗算:
4 * 5 = 20
これは、積を取り、要素の1つで除算することで元に戻すことができます
20 / 4 = 5
モジュロ除算:
22 % 7 = 1
除数を再構成するための商と被除数に対して実行できる演算がないため(またはその逆)、これを元に戻すことはできません。
「?」の場所を埋める操作を見つけることができますか?ですか?
1 ? 7 = 22
1 ? 22 = 7
そうは言っても、一方向ハッシュ関数はモジュロ除算と同じ数学的品質を持っています。
たとえば、1,000のロッカーがあるバスターミナルのロッカーの鍵をあなたに渡し、それを私の銀行員に届けるように頼んだとしましょう。疑わしいことは言うまでもなく、あなたは賢い人なので、すぐにキーを見て、キーに書かれているロッカー番号を確認します。これを知って、私はいくつかの不正なことをしました。最初に、モジュロ除算を使用して除算すると、1から1000の範囲の数値が得られる2つの数値が見つかりました。次に、元の数値を消去し、数値のペアから除数を書き込みました。次に、人々が鍵を使って1日に1つのロッカーのみを試すようにして、ロッカーを不正行為から保護します。第3に、銀行員はすでに配当を知っているので、鍵を受け取ったら、計算を行い、残りを見つけて、開くロッカーを知ることができます。
オペランドを賢く選択すると、商と被除数の1対1の関係に近づくことができます。答えは、可能な入力の結果を目的の数値の範囲に分散するため、各ロッカーを試す必要があります。ロッカーターミナルで利用できます。基本的に、それは、オペランドの1つを知っていても、残りについての知識を得ることができないことを意味します。
だから、私はあなたがそれがどのロッカーに属しているのか簡単に推測できることを心配することなく、その正当な所有者にキーを渡すことをあなたに「信頼」することができます。もちろん、すべてのロッカーをブルートフォースで検索できますが、銀行員がキーを使用してロッカーを空にするのに十分な時間を要します。
さまざまなハッシュ関数の詳細については、他の回答を参照してください。
これは非常に単純な例です。私が暗号学の初心者で、次のようなハッシュ関数を作成するとします。
_int SimpleHash(file) {
return 0 if file.length is even;
return 1 if file.length is odd;
}
_
これがテストです。SimpleHash(specialFile)
は0です。元のファイルは何でしたか?
明らかに、知る方法はありません(ただし、私のハッシュがファイルの長さに基づいていることはかなり簡単にわかるでしょう)。ハッシュにはファイルが行ったすべてのものが含まれていないため、ハッシュに基づいてファイルを「再構成」する方法はありません。
簡単に言えば、ハッシュ関数は、入力データを大きく絡ませて混乱させることで機能します。
たとえば MD5 を参照してください。入力データを512ビットブロックで処理します。各ブロックは16個の32ビットワードに分割されます。 64ステップあり、各ステップは16入力ワードの1つを使用します。したがって、各Wordはアルゴリズムの過程で4回使用されます。これが一方向性の源泉です。任意の入力ビットが複数の場所で入力され、そのような2つの入力の間で関数はすべての現在のデータを混合して、各入力ビットが128ビットの実行状態のほとんどに影響を与えるようにします。これにより、データの一部のみを確認して、関数を反転したり、衝突を計算したりできなくなります。 128ビット全体を見る必要があり、128ビットブロックのスペースは広すぎて効率的にウォークスルーできません。
現在、MD5はその機能の衝突を見つけることができるので、MD5はうまく機能しません。暗号技術者の観点から見ると、MD5はローテーションされた暗号化機能です。 1つのメッセージブロックM(512ビット)の処理は、入力状態V(128ビット値)を使用し、新しい状態V 'をV' = V + E(M、V)として計算します。ここで、 '+'はワード-賢い加算であり、「E」は対称暗号化関数(別名「ブロック暗号」)であり、Mをキーとして、Vを暗号化するメッセージとして使用します。よく見ると、E canはDESブロック暗号に似ており、2つの半分ではなく4つのクォーターを持つ、「拡張Feistelネットワーク」の一種です。詳細はここでは重要ではありません。私のポイントはその構造を使用するハッシュ関数(「Merkle-Damgård」と呼ばれる)の中で「良い」ハッシュ関数を作成するものは、ブロック暗号を「安全」にするものと類似しています。MD5での衝突攻撃の成功は、ツールである差分暗号解析これはそもそもブロック暗号を攻撃するために設計されました。
優れたブロック暗号から優れたハッシュ関数まで、却下すべきではないステップがあります。 Merkle-Damgård構造では、基になるブロック暗号が「関連するキー攻撃」に耐性がある場合、ハッシュ関数は安全です。対称暗号化の場合、関連するキー攻撃には実用的な機能がほとんどないため、ブロック暗号が強化されることはめったにありません。影響。たとえば、AES暗号化は、望まれるほど関連するキー攻撃に対して耐性がないことが判明し、これは一般的なパニックを引き起こしませんでした。その抵抗は、AESの設計時に求められていた特性の一部ではありませんでした。 AESをハッシュ関数に変換するのを防ぐだけです。 Wijrlpoolと呼ばれるハッシュ関数があり、これはRijndaelの派生物に基づいて構築されています。「Rijndael」はAESになったものの最初の名前です。しかしWhirlpoolは、関連する主要な攻撃に弱いRijndaelの部分を変更するように注意します。
また、ハッシュ関数の構築に使用できる他の構造があります。現在の標準関数(MD5、SHA-1、および「SHA-2」ファミリー、別名SHA-224、SHA-256、SHA-384、SHA-512)は、Merkle-Damgård関数ですが、後継者はそうではありません。 「SHA-3」と呼ばれる新しい標準ハッシュ関数を選択するために、NIST(その種のことを扱う米国連邦機関)が主催する進行中の競争があります。詳細は このページ を参照してください。現在、彼らは最初の51人から14人の候補者に減少しています(適切にコンパイルおよび実行されるコードを含む完全な送信を送信するという管理テストに失敗した追加のダースは数えません)。
より概念的な外観を見てみましょう。安全なハッシュ関数は、ランダムOracleのようになります。Oracleはブラックボックスであり、メッセージが表示されると[〜#〜] m [〜 #〜]を入力として、ランダムに選択された回答h(M)を出力スペースに出力します(つまり、すべてnビット文字列(ハッシュ関数の出力長がnの場合)。同じメッセージ[〜#〜] m [〜#〜]を入力として再度指定すると、Oracleは以前と同じ値を出力します。その制限は別として、以前に使用されていない入力[〜#〜] m [〜#〜]でのOracleの出力は予測できません。オラクルをサイコロを投げるgnomeのコンテナとして想像し、入力メッセージと対応する出力を大きな本に注意深く記録して、彼がOracleの契約を尊重するようにすることができます。 gnome自身はそれを知らないので、次の出力がどうなるかを予測する方法はありません。
ランダムなOracleが存在する場合、ハッシュ関数の反転にはコスト2 ^ nがあります。特定の出力を得るには、明確な入力メッセージを使用するよりも優れた方法はありません。期待値。ランダム選択が統一されているため、成功の確率は各試行で1 /(2 ^ n)であり、サイコロを投げるgnomeへの平均リクエスト数は2 ^ n。衝突(同じハッシュ値を生成する2つの異なる入力を見つける)の場合、コストは約* 1.4 * 2 ^(n/2)*です(大まかに言えば、* 1.4 * 2 ^(n/2)*出力の場合、約2 ^ nペアの出力をアセンブルします。各ペアは1 /(2 ^ n)の一致の確率を持っています。つまり、同じ出力を持つ2つの異なる入力)。これらは、ランダムなOracleで実行できる最高の方法です。
したがって、ランダムなOracleと同じくらい優れたハッシュ関数を探します。単純に関数を呼び出す場合よりも効率的に衝突を検出できないような方法で入力データを混合する必要があります2 ^(n/2)回。ハッシュ関数のベインは、数学的な構造、つまり、攻撃者がハッシュ関数の内部状態(少なくともnビットが大きい)を数学上のバリエーションとして表示できるショートカットですはるかに短い空間に住んでいるオブジェクト。対称暗号化システムに関する30年間の公的研究により、適用可能な概念とツール(拡散、雪崩、微分、直線性など)の道具全体が生み出されました。ただし、結論としては、ランダムなOracleが実際に存在する可能性があるという証拠はありません。攻撃できないハッシュ関数が欲しい。私たちが持っているものはハッシュ関数の候補であり、現在既知の攻撃はありません。どのsome種類の攻撃が機能しないことが証明できます。
やるべきことはまだあります。
ハッシュは(非常に)損失の多いエンコーディングです。
より簡単な例として、Xエンコーディングと呼ばれる5文字のワードの架空の2文字エンコーディングを想像してください。 Xエンコードのアルゴリズムは単純です。Wordの最初と最後の文字を受け取ります。
そう、
X-encode( SAUCE ) = SE
X-encode( BLOCK ) = BK
明らかに、エンコーディングSEからSAUCEを再構築することはできません(可能な入力の範囲がすべて5文字のワードであると想定しています)。言葉は簡単にスペースになる可能性があります。
余談ですが、SAUCEとSPACEの両方がエンコーディングとしてSEを生成するという事実はcollisionと呼ばれ、Xエンコーディングでは非常に優れたハッシュが作成されないことがわかります。 :)
アレイ
目を細めると、連想配列はハッシュのように見えます。主な違いは、ハッシュ名に%記号がないことと、一度に1つのキーしか割り当てられないことです。したがって、_$foo{'key'} = 1;
_と言いますが、@keys = keys(foo);
だけです。それぞれ、キー、値などの使い慣れた関数は、現在と同様に機能しました(削除はPerl 2で追加されました)。
Perl 3には3つの完全なデータ型がありました:ハッシュ名に%記号があり、ハッシュ全体を一度に割り当てることができ、dbmopenが追加されました(現在はtieのために非推奨です)。 Perl 4はコンマ区切りのハッシュキーを使用して多次元配列をエミュレートしました(配列参照でより適切に処理されるようになりました)。
Perl 5は、連想配列をハッシュと呼ぶ大きな飛躍を遂げました。 (私が知る限り、「ハッシュテーブル」や類似のものではなく、データ構造を参照した最初の言語です。)皮肉にも、関連するコードをhash.cからhv.cに移動しました。
命名法
辞書は、前に説明したように、一意のキーによってインデックス付けされた値の順序付けられていないコレクションです。それらは、連想配列またはマップと呼ばれることもあります。それらはいくつかの方法で実装できます。その1つはハッシュテーブルと呼ばれるデータ構造を使用する方法です(Perlはこれをハッシュと呼びます)。
Perlが「ハッシュ」という用語を使用することは、ハッシュ関数の出力がハッシュ(特に暗号化のコンテキスト)と呼ばれることもあり、ハッシュテーブルは通常他の場所ではハッシュと呼ばれないため、混乱を招く可能性があります。
安全のために、データ構造をハッシュテーブルとして参照し、「ハッシュ」という用語は、Perl固有の明確なコンテキストでのみ使用してください。