web-dev-qa-db-ja.com

ハッシュアルゴリズムと暗号化アルゴリズムの基本的な違い

私はハッシュと暗号化アルゴリズムの間で多くの混乱を見ます、そして私は私達に関してもう少し専門的なアドバイスを聞きたいです。

  1. ハッシュ対暗号化を使用する場合

  2. ハッシュまたは暗号化アルゴリズムを(理論的/数学的レベルから)異なるものにするもの、すなわちハッシュを不可逆にするもの(Rainbowツリーの助けを借りずに)

ここにいくつかの 類似 SO私が探していたほど詳細には入らなかった質問があります。

難読化、ハッシュ、暗号化の違いは何ですか?
暗号化とハッシュの違い

480
Kenny Cason

まあ、あなたはそれを Wikipedia ...で調べることができますが、説明が欲しいので、ここでベストを尽くします:

ハッシュ関数

これらは、任意の長さの入力と(通常)固定長(またはより短い長さ)の出力との間のマッピングを提供します。単純なcrc32から、MD5やSHA1/2/256/512などの完全な暗号化ハッシュ関数まで、何でもかまいません。ポイントは、一方向のマッピングが行われているということです。すべての関数は、入力可能な出力よりも小さな出力を生成するため、常にmany:1マッピングです(常に衝突が発生することを意味します)(可能なすべての1mbファイルをMD5にフィードすると、大量の衝突が発生します)。

リバースするのが難しい(または実用上不可能)理由は、それらが内部的に機能するためです。ほとんどの暗号化ハッシュ関数は、入力セットを何度も繰り返して出力を生成します。したがって、入力の各固定長チャンク(アルゴリズムに依存)を見ると、ハッシュ関数は現在の状態を呼び出します。次に、状態を反復処理して新しい状態に変更し、それをフィードバックとして使用します(MD5は、データの512ビットチャンクごとに64回これを行います)。次に、これらすべての反復からの結果の状態を何らかの方法で結合して、結果のハッシュを形成します。

ここで、ハッシュをデコードする場合、最初に、指定されたハッシュを反復状態に分割する方法を理解する必要があります(1つの入力がデータのチャンクのサイズよりも小さい可能性があります。次に、各状態の反復を逆にする必要があります。さて、これが非常に難しい理由を説明するために、次の式からabを推定しようと想像してください:10 = a + b。機能するabには10の正の組み合わせがあります。それを何度もループします:tmp = a + b; a = b; b = tmp。 64回の反復では、10 ^ 64を超える可能性があります。そして、それは、ある状態が反復から反復へ保存される単純な追加です。実際のハッシュ関数は1つ以上の操作を実行します(MD5は4つの状態変数に対して約15の操作を実行します)。また、次の反復は前の状態に依存し、現在の状態の作成時に前の状態が破壊されるため、特定の出力状態につながった入力状態を判別することはほとんど不可能です(反復ごとに)。多数の可能性を伴い、それを組み合わせると、MD5でさえデコードはほぼ無限の(しかし無限ではない)量のリソースを必要とします。非常に多くのリソースがあるため、ハッシュのデコードを試みるよりも、入力のサイズ(小さい入力の場合)がわかっている場合、ハッシュをブルートフォースする方が実際にはかなり安価です。

暗号化機能

これらは、任意の長さの入力と出力の間の1:1マッピングを提供します。そして、それらは常に可逆的です。注意すべき重要なことは、何らかの方法を使用して元に戻すことができるということです。また、特定のキーでは常に1:1です。現在、同じ出力を生成する可能性のある複数のinput:keyペアがあります(実際には、暗号化関数に応じて、通常あります)。優れた暗号化データは、ランダムノイズと見分けがつきません。これは、常に一貫した形式の適切なハッシュ出力とは異なります。

ユースケース

値を比較したいが、プレーン表現を保存できない場合(いくつかの理由で)ハッシュ関数を使用します。パスワードは、セキュリティ上の理由からプレーンテキストを保存したくないので、このユースケースに非常によく適合する必要があります(そうすべきではありません)。しかし、海賊版音楽ファイルのファイルシステムをチェックしたい場合はどうでしょうか?音楽ファイルごとに3 MBを保存することは実用的ではありません。その代わりに、ファイルのハッシュを取得して保存します(md5は3MBではなく16バイトを保存します)。この方法では、各ファイルをハッシュし、保存されているハッシュのデータベースと比較するだけです(再エンコード、ファイルヘッダーの変更などのため、実際にはうまくいきませんが、これはユースケースの例です)。

入力データの有効性を確認するときにハッシュ関数を使用します。それは彼らが設計されたものです。 2つの入力があり、それらが同じかどうかを確認する場合は、両方をハッシュ関数で実行します。入力サイズが小さい場合、衝突の確率は天文学的に低くなります(適切なハッシュ関数を想定)。それがパスワードに推奨される理由です。 32文字までのパスワードの場合、md5には4倍の出力スペースがあります。 SHA1には、約6倍の出力スペースがあります。 SHA512の出力スペースは約16倍です。パスワードが何であるかはあまり気にしません。保存されているパスワードと同じかどうかは気にします。そのため、パスワードにハッシュを使用する必要があります。

入力データを取り戻す必要がある場合は常に暗号化を使用します。 Wordneedに注意してください。クレジットカード番号を保存する場合は、ある時点で元に戻す必要がありますが、プレーンテキストは保存しないでください。代わりに、暗号化されたバージョンを保存し、キーを可能な限り安全に保管してください。

ハッシュ関数はデータの署名にも最適です。たとえば、HMACを使用している場合、送信されていない既知の値(シークレット値)と連結されたデータのハッシュを取得して、データに署名します。したがって、プレーンテキストとHMACハッシュを送信します。次に、受信者は送信されたデータを既知の値で単純にハッシュし、送信されたHMACと一致するかどうかを確認します。同じであれば、秘密の価値のないパーティーによって改ざんされていないことがわかります。これは、HTTPフレームワークによる安全なCookieシステムや、データの整合性を保証するHTTPを介したデータのメッセージ送信で一般的に使用されます。

パスワードのハッシュに関する注意:

暗号化ハッシュ関数の重要な特徴は、作成が非常に高速であり、veryリバース/リバースが困難/遅いことです(実際には不可能であるほど) )。これにより、パスワードに問題が生じます。 sha512(password)を保存する場合、Rainbowテーブルまたはブルートフォース攻撃から保護することはできません。ハッシュ関数は高速化のために設計されたことを忘れないでください。したがって、攻撃者がハッシュ関数を使用して辞書を実行し、各結果をテストすることは簡単です。

ソルトを追加すると、ハッシュに不明なデータが少し追加されるため、問題に役立ちます。したがって、md5(foo)に一致するものを見つける代わりに、既知のソルトに追加するとmd5(foo.salt)を生成するものを見つける必要があります(これは非常に困難です)。ただし、塩を知っている場合は辞書を調べるだけなので、速度の問題は解決しません。

そのため、これに対処する方法があります。人気のある方法の1つは、 キー強化 (またはキーストレッチ)と呼ばれます。基本的に、ハッシュを何度も(通常は数千回)繰り返します。これは2つのことを行います。まず、ハッシュアルゴリズムの実行時間が大幅に遅くなります。第二に、正しく実装された場合(各反復で入力とソルトを渡す)、出力のエントロピー(使用可能なスペース)を実際に増やし、衝突の可能性を減らします。簡単な実装は次のとおりです。

var hash = password + salt;
for (var i = 0; i < 5000; i++) {
    hash = sha512(hash + password + salt);
}

PBKDF2BCrypt など、他のより標準的な実装があります。しかし、この手法は、多くのセキュリティ関連システム(PGP、WPA、Apache、OpenSSLなど)で使用されています。

一番下の行hash(password)は十分ではありません。 hash(password + salt)は優れていますが、それでも十分ではありません...ストレッチハッシュメカニズムを使用してパスワードハッシュを生成します...

些細なストレッチに関する別の注意

どのような状況でも、1つのハッシュの出力を直接ハッシュ関数にフィードバックしないでください

hash = sha512(password + salt); 
for (i = 0; i < 1000; i++) {
    hash = sha512(hash); // <-- Do NOT do this!
}

この理由は衝突に関係しています。可能な出力スペース(可能な出力の数)は入力スペースよりも小さいため、すべてのハッシュ関数には衝突があることに注意してください。理由を見るために、何が起こるか見てみましょう。これを前置きするために、sha1()(実際にはmuchからの衝突の確率が0.001%であると仮定してみましょう。目的)。

hash1 = sha1(password + salt);

現在、hash1の衝突確率は0.001%です。しかし、次のhash2 = sha1(hash1);を実行すると、hash1のすべての衝突が自動的にhash2の衝突になります。したがって、ハッシュ1のレートは0.001%になり、2回目のsha1()コールがそれに追加されます。したがって、hash2の衝突の確率は0.002%です。それは2倍のチャンスです!各反復により、衝突の別の0.001%チャンスが結果に追加されます。そのため、1000回の反復で、衝突の可能性はわずかな0.001%から1%に跳ね上がりました。現在、劣化は線形であり、実際の確率はfarより小さいですが、効果は同じです(単一の衝突の可能性の推定md5は約1 /(2128)または1 /(3x1038)。それは小さいように見えますが、 誕生日攻撃 のおかげで、実際にはそれほど小さくありません)。

代わりに、毎回ソルトとパスワードを再追加することにより、ハッシュ関数にデータを再導入しています。したがって、特定のラウンドの衝突は、次のラウンドの衝突ではなくなります。そう:

hash = sha512(password + salt);
for (i = 0; i < 1000; i++) {
    hash = sha512(hash + password + salt);
}

ネイティブのsha512関数と同じ衝突の可能性があります。それはあなたが望むものです。代わりにそれを使用してください。

712
ircmaxell

ハッシュ関数は、パンを焼くのと同じと見なすことができます。入力(小麦粉、水、イーストなど)から始めて、ハッシュ関数を適用した後(ミキシング+ベーキング)、出力になります。それはパンの塊です。

パンを小麦粉、水、酵母に分離することはできません。そのうちのいくつかは製パン工程で失われ、水や小麦粉や酵母がどれだけの量のために使われたのか正確にはわかりませんその情報はハッシュ関数(別名オーブン)によって破壊されたためです。

理論的には、さまざまな種類のインプットが同一のパンを生成します(例:2カップの水と1tsbpの酵母が2.1カップの水と0.9tsbpの酵母とまったく同じローフを生成します)。まさに入力の組み合わせがそれを生み出したのです。

一方、暗号化は安全なデポジットボックスと見なすことができます。あなたがそこに入れたものは何でもあなたがそれが最初の場所でそれをロックされていた鍵を持っている限り、戻ってくる。これは対称的な操作です。あるキーといくつかの入力があれば、特定の出力が得られます。その出力と同じキーを考えると、元の入力に戻ります。それは1:1のマッピングです。

154
Marc B

元の入力を取り戻したくない場合はハッシュを使用し、行う場合は暗号化を使用してください。

ハッシュはいくつかの入力を受け取り、それをいくつかのビットに変換します(通常は32ビット整数、64ビット整数などのように数値として考えられます)。同じ入力でも常に同じハッシュが生成されますが、その過程で主に情報が失われるため、元の入力を確実に再現することはできません(ただし、注意点がいくつかあります)。

暗号化は、あなたが暗号化機能に入力したすべての情報を主に保存し、特定の鍵を持たずに誰かが元の入力に戻ることを難しくします(理想的には不可能)。

ハッシュの簡単な例

これは、ハッシュが元の入力を取り戻すことができない理由を理解するのに役立つ簡単な例です。 1ビットハッシュを作成しているとしましょう。私のハッシュ関数は入力としてビット文字列を取り、入力文字列に偶数のビットが設定されていればハッシュを1に設定し、そうでなければ奇数が設定されていたら0に設定します。

例:

Input    Hash
0010     0
0011     1
0110     1
1000     0

ハッシュが0になる入力値が多く、ハッシュが1になる入力値が多数あります。ハッシュが0であることがわかっている場合、元の入力が何であるかを確実に知ることはできません。

ちなみに、この1ビットハッシュは厳密には考案されていません... パリティビット を見てください。

暗号化の簡単な例

例えば、入力がAの場合はBと入力します。入力がBの場合はCと入力します。入力がZの場合は、入力はAです。もう一度Aを書く。

Input   Encrypted
CAT     DBU
Zoo     APP

単純なハッシュの例と同じように、このタイプの暗号化には 歴史的に使用されていました があります。

41
Eric J.

ハッシュと暗号化/復号化技術の基本的な概要は次のとおりです。

ハッシュ:

hash any plain text再度ハッシュされたテキストから同じプレーンテキストを取得できません。単純に、それは一方向のプロセスです。

hashing


暗号化と復号化:

encrypt any plain textキーを再度使用すると同じプレーンテキストを取得できる暗号化されたテキストでdecryptionを実行する同じ(対称)/ diffrent(asymentric)キーを使用します。

encryption and decryption


PDATE:編集された質問に記載されているポイントに対処します。

1。ハッシュと暗号化のどちらを使用するか

Hashingは、誰かにファイルを送信したい場合に便利です。ただし、他の誰かがファイルを傍受して変更する可能性があります。そのため、ハッシュ値を公開する場合、受信者が正しいファイルであることを確認できます。これにより、受信者は受信したファイルのハッシュ値を計算し、ハッシュ値と一致することを確認できます。

暗号化は、誰かに送信するメッセージがあると言う場合に適しています。メッセージをキーで暗号化し、受信者が同じ(または場合によっては別の)キーで復号化して、元のメッセージを取得します。 クレジット


2。ハッシュまたは暗号化アルゴリズムを(理論的/数学的なレベルから)異なるものにするもの、つまりハッシュを不可逆的にするもの(レインボーツリーの助けなし)

基本的にハッシュは暗号化ではなく情報を失う操作です。理解を容易にするために、単純な数学的な方法で違いを見てみましょう、もちろん、両方とも反復を伴うはるかに複雑な数学演算があります

暗号化/復号化(リバーシブル):

追加

4 + 3 = 7  

これは、合計を取得し、加数の1つを減算することで逆にできます

7 - 3 = 4     

乗算

4 * 5 = 20  

これは、製品を取得し、要因の1つで割ることによって元に戻すことができます

20 / 4 = 5    

したがって、ここでは、加数/因子の1つが暗号解読キーであり、result(7,20)が暗号化されたテキストであると想定できます。


ハッシュ(リバーシブルではありません):

モジュロ除算

22 % 7 = 1   

商と被除数に対して除数を再構成する(またはその逆)ことができる操作がないため、これを元に戻すことはできません。

「?」を入力する操作を見つけることができますか?は?

1  ?  7 = 22  
1  ?  22 = 7

したがって、ハッシュ関数はモジュロ除算と同じ数学的品質を持ち、情報を失います。

クレジット

37
mrsrinivas

私の唯一のライナー...一般的にインタビュアーは以下の答えを望んでいました。

ハッシュは一方向です。ハッシュコードからデータや文字列を変換することはできません。

暗号化は双方向です - あなたがあなたとあなたの鍵を持っていれば、あなたは再び暗号化された文字列を復号化することができます。

25
Shiv Mohan

ハッシュ関数 可変サイズのテキストを固定サイズのテキストに変換します。

Hash

ソース: https://en.wikipedia.org/wiki/Hash_function

実際に見てみましょう。私はそれのためにphpを使います。

ハッシュ:

$str = 'My age is 29';
$hash = hash('sha1', $str);
echo $hash; // OUTPUT: 4d675d9fbefc74a38c89e005f9d776c75d92623e

デハッシュ:

SHA1は一方向ハッシュです。つまり、ハッシュを抹消することはできません。ただし、ハッシュをブルートフォースすることはできます。ご覧ください: https://hashkiller.co.uk/sha1-decrypter.aspx

MD5、別のハッシュです。 MD5デハッシャーはこのWebサイトで見つけることができます: https://www.md5online.org/ /.


暗号化関数 は、暗号化キーを使用してテキストを無意味な暗号文に変換します。 enter image description here

ソース: https://en.wikipedia.org/wiki/Encryption

暗号化を処理するPHPコードを見てみましょう。

--- Mcryptの拡張---

暗号化:

$cipher = MCRYPT_RIJNDAEL_128;
$key = 'A_KEY';
$data = 'My age is 29';
$mode = MCRYPT_MODE_ECB;

$encryptedData = mcrypt_encrypt($cipher, $key , $data , $mode);
var_dump($encryptedData);

//OUTPUT:
string '„Ùòyªq³¿ì¼üÀpå' (length=16)

復号化:

$decryptedData = mcrypt_decrypt($cipher, $key , $encryptedData, $mode);
$decryptedData = rtrim($decryptedData, "\0\4"); // Remove the nulls and EOTs at the END
var_dump($decryptedData);

//OUTPUT:
string 'My age is 29' (length=12)

--- OpenSSLの拡張---

Mcryptエクステンションは7.1で廃止されました。そしてphp 7.2で削除されました。 OpenSSLの拡張機能はphp 7で使われるべきです。下記のコードスニペットを見てください:

$key = 'A_KEY';
$data = 'My age is 29';

// ENCRYPT
$encryptedData = openssl_encrypt($data , 'AES-128-CBC', $key, 0, 'IV_init_vector01');
var_dump($encryptedData);

// DECRYPT    
$decryptedData = openssl_decrypt($encryptedData, 'AES-128-CBC', $key, 0, 'IV_init_vector01');
var_dump($decryptedData);

//OUTPUT
string '4RJ8+18YkEd7Xk+tAMLz5Q==' (length=24)
string 'My age is 29' (length=12)
15
Julian

対称暗号化:

対称暗号化は、共有キー暗号化または共有秘密暗号化とも呼ばれます。対称暗号化では、トラフィックの暗号化と復号化の両方に単一の鍵が使用されます。

enter image description here

非対称暗号化:

非対称暗号化は、公開鍵暗号化とも呼ばれます。非対称暗号化は、主に2つのキーが使用されるという点で対称暗号化と異なります。1つは暗号化用、もう1つは復号化用です。最も一般的な非対称暗号化アルゴリズムはRSAです。

対称暗号化と比較して、非対称暗号化は計算上の負担が大きく、はるかに遅くなる傾向があります。したがって、ペイロードデータを保護するために通常使用されることはありません。その代わりに、その最大の強みは、安全でない媒体(インターネットなど)を介して安全なチャネルを確立できることです。これは、データの暗号化にしか使用できない公開鍵の交換によって実現されます。決して共有されない補完的な秘密鍵は、復号化に使用されます。

enter image description here

ハッシュ:

最後に、ハッシュは暗号化とは異なる暗号セキュリティの一種です。暗号化は、最初にメッセージを暗号化してから復号化するために使用される2段階のプロセスですが、ハッシュはメッセージを不可逆的な固定長の値、つまりハッシュに圧縮します。ネットワーキングで見られる2つの最も一般的なハッシュアルゴリズムはMD5SHA-1です。

enter image description here

ここでもっと読んでください: http://packetlife.net/blog/2010/nov/23/symmetric-asymmetric-encryption-hashing/

9

暗号化アルゴリズムとハッシュアルゴリズムも同様に機能します。いずれの場合も、 混乱と拡散 を作り出す必要があります。簡潔に言うと、 confusion は鍵と暗号文の間に複雑な関係を作り出しており、 diffusion は各ビットの情報を広げています。

多くのハッシュ関数は実際には暗号化アルゴリズム(または暗号化アルゴリズムのプリミティブ)を使用します。例えば、SHA-3候補 Skein はThreefishを各ブロックを処理する基本的な方法として使用します。それらは破壊的に、決定論的に固定長に結合されています

4
Justin Morgan
  1. 一方向に進むだけの場合はハッシュを使用します。たとえば、システム内のパスワードの場合は、ハッシュ化を使用します。ハッシュ化後にユーザーが入力した値がリポジトリ内の値と一致することを確認するだけだからです。暗号化では、2つの方法があります。

  2. ハッシュアルゴリズムと暗号化アルゴリズムは単なる数学的アルゴリズムです。つまり、その点では違いはありません。すべて数学式です。しかし、意味論的には、ハッシュ(一方向)と暗号化(双方向)の間には非常に大きな違いがあります。ハッシュはなぜ不可逆的なのですか?それらがそのようになるように設計されているので、時にはあなたは一方向の操作が欲しいからです。

4
hvgotcodes

データを送信するためのセキュリティ、つまり双方向通信では暗号化を使用します。すべての暗号化にはキーが必要です。

認証に関しては、ハッシュを使用します。ハッシュの鍵はありません。

ハッシュは、任意の量のデータ(バイナリまたはテキスト)を受け取り、そのデータのチェックサムを表す固定長ハッシュを作成します。たとえば、ハッシュは16バイトです。異なるハッシュアルゴリズムは異なるサイズのハッシュを生成します。明らかに元のデータをハッシュから再作成することはできませんが、同じハッシュ値が生成されるかどうかを確認するためにデータを再度ハッシュすることはできます。一方向のUnixベースのパスワードはこのように機能します。パスワードはハッシュ値として保存され、システムにログオンするために、入力したパスワードはハッシュされ、ハッシュ値は実際のパスワードのハッシュと比較されます。それらが一致する場合は、正しいパスワードを入力したはずです。

なぜハッシュは元に戻せないのか

ハッシュから入力へのマッピングは1対1ではないため、ハッシュは元に戻せません。 2つの入力を同じハッシュ値にマッピングすることは、通常「ハッシュ衝突」と呼ばれます。セキュリティ目的のために、「良い」ハッシュ関数の特性の1つは衝突が実用的にまれであるということです。

4
ayush