「ダブルハッシュ」は、一度だけハッシュするよりも安全性が低いですか?


293

保存する前にパスワードを2回ハッシュすることは、1回だけハッシュするよりも安全ですか?

私が話しているのはこれを行うことです:

$hashed_password = hash(hash($plaintext_password));

これだけではなく:

$hashed_password = hash($plaintext_password);

安全性が低い場合、適切な説明(またはリンク)を提供できますか?

また、使用されるハッシュ関数は違いを生みますか?同じハッシュ関数を繰り返す代わりに、md5とsha1を(たとえば)混在させると、違いはありますか?

注1:「ダブルハッシュ」とは、パスワードをよりわかりにくくするために、パスワードを2回ハッシュすることを指します。私は衝突を解決するためテクニックについて話しているのではありません。

注2:本当に安全にするために、ランダムなソルトを追加する必要があることはわかっています。問題は、同じアルゴリズムで2回ハッシュすることがハッシュを助けるか傷つけるかです。


2
Hash(password)そしてHash(Hash(password))同様に安全ではありません。どちらにもセマンティックセキュリティの概念がありません。つまり、出力ランダム区別可能です。たとえばMD5("password")です5f4dcc3b5aa765d61d8327deb882cf99。これはのMD5ハッシュでありpassword、ランダム区別できます。代わりに、HMACを使用する必要があります。その証明可能な安全性とそのPRF。
jww 2014年

回答:


267

一度パスワードをハッシュするのは安全ではありません

いいえ、複数のハッシュはそれほど安全ではありません。それらは安全なパスワードの使用の重要な部分です。

ハッシュを反復すると、攻撃者が候補リストの各パスワードを試すのにかかる時間が長くなります。パスワードを攻撃するのにかかる時間を数時間から数年に簡単に増やすことができます。

単純な反復では十分ではありません

ハッシュ出力を入力にチェーンするだけでは、セキュリティ上十分ではありません。反復は、パスワードのエントロピーを保持するアルゴリズムのコンテキストで行われる必要があります。幸いなことに、設計に信頼を与えるのに十分な精査があった公開アルゴリズムがいくつかあります。

PBKDF2のような優れた鍵導出アルゴリズムは、ハッシュの各ラウンドにパスワードを注入し、ハッシュ出力の衝突に関する懸念を軽減します。PBKDF2は、そのままパスワード認証に使用できます。Bcryptは、暗号化ステップを使用して鍵の導出に従います。このようにして、キーの派生を逆にする高速な方法が発見された場合でも、攻撃者は既知のプレーンテキスト攻撃を完了する必要があります。

パスワードを破る方法

保存されたパスワードには、オフライン攻撃からの保護が必要です。パスワードがソルト化されていない場合、事前に計算された辞書攻撃(たとえば、レインボーテーブルを使用)によってパスワードが破られる可能性があります。それ以外の場合、攻撃者は各パスワードのハッシュを計算し、保存されているハッシュと一致するかどうかを確認するために時間を費やす必要があります。

すべてのパスワードが同じ可能性があるわけではありません。攻撃者はすべての短いパスワードを徹底的に検索する可能性がありますが、ブルートフォースで成功する可能性は、文字が1つ増えるごとに急激に低下することを知っています。代わりに、最も可能性の高いパスワードの順序付きリストを使用します。「password123」で始まり、使用頻度の低いパスワードに進みます。

攻撃者リストが長く、100億人の候補者があるとします。また、デスクトップシステムが1秒あたり100万ハッシュを計算できるとします。攻撃者は、反復を1回だけ使用した場合、リスト全体を3時間未満でテストできます。しかし、2000回の反復が使用された場合、その時間はほぼ8か月に延長されます。より洗練された攻撃者(たとえば、GPUの能力を利用できるプログラムをダウンロードできる攻撃者)を倒すには、より多くの反復が必要です。

いくらですか?

使用する反復数は、セキュリティとユーザーエクスペリエンスのトレードオフです。攻撃者が使用できる専用ハードウェアは安価ですが、それでも1秒あたり数億回の反復を実行できます。攻撃者のシステムのパフォーマンスは、反復回数を考慮してパスワードを解読するのにかかる時間を決定します。ただし、アプリケーションでこの専用ハードウェアを使用することはほとんどありません。ユーザーを悪化させることなく実行できる反復の数はシステムによって異なります

認証中にユーザーにauthentication秒ほど待機させることができます。ターゲットプラットフォームのプロファイルを作成し、できるだけ多くの反復を使用します。私がテストしたプラットフォーム(モバイルデバイスの1人のユーザー、またはサーバープラットフォームの多くのユーザー)は、60,000〜120,000回の反復でPBKDF2を快適にサポートでき、コスト係数が12または13のbcryptをサポートできます。

より多くの背景

ハッシュにおけるソルトとイテレーションの役割に関する信頼できる情報については、PKCS#5を読んでください。PBKDF2はパスワードから暗号化キーを生成するためのものでしたが、パスワード認証のための一方向ハッシュとしてうまく機能します。bcryptの各反復はSHA-2ハッシュよりもコストがかかるため、使用できる反復は少なくなりますが、考え方は同じです。Bcryptは、既知のプレーンテキストを暗号化するために派生キーを使用することにより、ほとんどのPBKDF2ベースのソリューションをさらに一歩前進します。結果の暗号化テキストは、いくつかのメタデータとともに「ハッシュ」として格納されます。ただし、PBKDF2で同じことを行うことを妨げるものは何もありません。

このトピックについて私が書いた他の回答は次のとおりです。


68
侵害された認証ストアに対する辞書攻撃を防ごうとする場合、意図的に遅いアルゴリズムを作成することは受け入れられている習慣です。この手法は、「キー強化」または「キーストレッチ」と呼ばれます。en.wikipedia.org/wiki/Key_stretchingを

17
@RoBorg:それはどのように遅くなる問題ではありません、あなたの実装があるが、どのように攻撃者の実装が可能になるスロー:ハッシュ自体が遅く何千回であれば、それは長いパスワードをブルートフォースへと倍の攻撃者の何千もかかります。
orip 08

5
間違いなく、128ビット空間0から2 ^ 128-1内での衝突が必要で​​す。ハッシュアルゴリズムの2 ^ 128出力スペースが完全である場合、理論的には、2 ^ 128グリフのアルファベットの置換暗号があります。
jmucchiello 2009年

13
@devin-「私の解決策」ではありません。広く受け入れられている手法であり、PKCS#5などのパスワードベースの暗号化標準に組み込まれ、Robert Morrisなどの専門家によって推奨されています。正当なアプリケーションでは、ユーザーの認証に費やされる時間の割合が少ないため、非常にスケーラブルです。アプリケーションがパスワードを解読しているときにのみスケーリングが難しくなるため、推奨事項です。確かに、ハッシュの検索スペースは考えられるパスワードの検索スペースよりも小さいですが、128ビットのスペースでさえ、ブルートフォース検索には大きすぎます。防御する脅威は、オフライン辞書攻撃です。
エリクソン2009年

6
個々のユーザーの不便ではなく、ユーザー数が多い場合にサーバーにかかるストレスについて言及しました。これは、CPU負荷に依存してリクエストの数を遅くしているためです。つまり、CPUパワーを追加すると、ブルートフォース攻撃者に対する制限が緩和されます。-しかし、あなたはスケーラビリティと広く受け入れられている慣行について完全に正しいです。以前のコメントで述べたほとんどすべてのことについて私は間違っていました。すみません:)
DevinB 2009年

227

安全だと言う人にとって、彼らは一般的に正しいです。"二重"ハッシュ(またはその論理的拡張、ハッシュ関数の反復)は、特定の問題について、正しく実行されれば完全に安全です

安全でないと言う人にとって、この場合は正しいです。質問に投稿されたコード安全ではありません。その理由について話しましょう:

$hashed_password1 = md5( md5( plaintext_password ) );
$hashed_password2 = md5( plaintext_password );

私たちが心配しているハッシュ関数には2つの基本的な特性があります。

  1. プリイメージレジスタンス -ハッシュが与えられた場合、次の$hようなメッセージを見つけるのは難しいはず$mです。$h === hash($m)

  2. 2番目のプリイメージ耐性 -メッセージが与えられた場合、次の$m1ような別のメッセージを見つけることは難しいはず$m2です。hash($m1) === hash($m2)

  3. 衝突耐性 -次のようなメッセージのペアを見つけるのは難しいはず($m1, $m2)ですhash($m1) === hash($m2)(これはSecond-Pre-Image耐性と似ていますが、攻撃者が両方のメッセージを制御できるという点で異なります)...

パスワードの保存に関して、私たちが本当に気にしているのは、プリイメージ耐性です。他の2つ$m1は、私たちが安全を確保しようとしているユーザーのパスワードであるため、意味がありません。したがって、攻撃者がすでに持っている場合、ハッシュには何も保護されません...

免責事項

以下のすべては、私たちが関心を持っているのはプレイメージ耐性であるという前提に基づいています。ハッシュ関数の他の2つの基本的なプロパティは、同じように機能しない場合があります(通常は機能しません)。したがって、この投稿の結論は、パスワードの保存にハッシュ関数を使用する場合にのみ適用されます。それらは一般的に適用されません...

始めましょう

この説明のために、独自のハッシュ関数を作成してみましょう。

function ourHash($input) {
    $result = 0;
    for ($i = 0; $i < strlen($input); $i++) {
        $result += ord($input[$i]);
    }
    return (string) ($result % 256);
}

これで、このハッシュ関数が何をするかはかなり明白になります。入力の各文字のASCII値を合計し、その結果を256で剰余します。

それをテストしてみましょう:

var_dump(
    ourHash('abc'), // string(2) "38"
    ourHash('def'), // string(2) "47"
    ourHash('hij'), // string(2) "59"
    ourHash('klm')  // string(2) "68"
);

ここで、関数の周りで数回実行するとどうなるかを見てみましょう。

$tests = array(
    "abc",
    "def",
    "hij",
    "klm",
);

foreach ($tests as $test) {
    $hash = $test;
    for ($i = 0; $i < 100; $i++) {
        $hash = ourHash($hash);
    }
    echo "Hashing $test => $hash\n";
}

それは出力します:

Hashing abc => 152
Hashing def => 152
Hashing hij => 155
Hashing klm => 155

うーん、すごい。衝突が発生しました!!! その理由を見てみましょう:

以下は、可能なすべてのハッシュ出力の文字列をハッシュした出力です。

Hashing 0 => 48
Hashing 1 => 49
Hashing 2 => 50
Hashing 3 => 51
Hashing 4 => 52
Hashing 5 => 53
Hashing 6 => 54
Hashing 7 => 55
Hashing 8 => 56
Hashing 9 => 57
Hashing 10 => 97
Hashing 11 => 98
Hashing 12 => 99
Hashing 13 => 100
Hashing 14 => 101
Hashing 15 => 102
Hashing 16 => 103
Hashing 17 => 104
Hashing 18 => 105
Hashing 19 => 106
Hashing 20 => 98
Hashing 21 => 99
Hashing 22 => 100
Hashing 23 => 101
Hashing 24 => 102
Hashing 25 => 103
Hashing 26 => 104
Hashing 27 => 105
Hashing 28 => 106
Hashing 29 => 107
Hashing 30 => 99
Hashing 31 => 100
Hashing 32 => 101
Hashing 33 => 102
Hashing 34 => 103
Hashing 35 => 104
Hashing 36 => 105
Hashing 37 => 106
Hashing 38 => 107
Hashing 39 => 108
Hashing 40 => 100
Hashing 41 => 101
Hashing 42 => 102
Hashing 43 => 103
Hashing 44 => 104
Hashing 45 => 105
Hashing 46 => 106
Hashing 47 => 107
Hashing 48 => 108
Hashing 49 => 109
Hashing 50 => 101
Hashing 51 => 102
Hashing 52 => 103
Hashing 53 => 104
Hashing 54 => 105
Hashing 55 => 106
Hashing 56 => 107
Hashing 57 => 108
Hashing 58 => 109
Hashing 59 => 110
Hashing 60 => 102
Hashing 61 => 103
Hashing 62 => 104
Hashing 63 => 105
Hashing 64 => 106
Hashing 65 => 107
Hashing 66 => 108
Hashing 67 => 109
Hashing 68 => 110
Hashing 69 => 111
Hashing 70 => 103
Hashing 71 => 104
Hashing 72 => 105
Hashing 73 => 106
Hashing 74 => 107
Hashing 75 => 108
Hashing 76 => 109
Hashing 77 => 110
Hashing 78 => 111
Hashing 79 => 112
Hashing 80 => 104
Hashing 81 => 105
Hashing 82 => 106
Hashing 83 => 107
Hashing 84 => 108
Hashing 85 => 109
Hashing 86 => 110
Hashing 87 => 111
Hashing 88 => 112
Hashing 89 => 113
Hashing 90 => 105
Hashing 91 => 106
Hashing 92 => 107
Hashing 93 => 108
Hashing 94 => 109
Hashing 95 => 110
Hashing 96 => 111
Hashing 97 => 112
Hashing 98 => 113
Hashing 99 => 114
Hashing 100 => 145
Hashing 101 => 146
Hashing 102 => 147
Hashing 103 => 148
Hashing 104 => 149
Hashing 105 => 150
Hashing 106 => 151
Hashing 107 => 152
Hashing 108 => 153
Hashing 109 => 154
Hashing 110 => 146
Hashing 111 => 147
Hashing 112 => 148
Hashing 113 => 149
Hashing 114 => 150
Hashing 115 => 151
Hashing 116 => 152
Hashing 117 => 153
Hashing 118 => 154
Hashing 119 => 155
Hashing 120 => 147
Hashing 121 => 148
Hashing 122 => 149
Hashing 123 => 150
Hashing 124 => 151
Hashing 125 => 152
Hashing 126 => 153
Hashing 127 => 154
Hashing 128 => 155
Hashing 129 => 156
Hashing 130 => 148
Hashing 131 => 149
Hashing 132 => 150
Hashing 133 => 151
Hashing 134 => 152
Hashing 135 => 153
Hashing 136 => 154
Hashing 137 => 155
Hashing 138 => 156
Hashing 139 => 157
Hashing 140 => 149
Hashing 141 => 150
Hashing 142 => 151
Hashing 143 => 152
Hashing 144 => 153
Hashing 145 => 154
Hashing 146 => 155
Hashing 147 => 156
Hashing 148 => 157
Hashing 149 => 158
Hashing 150 => 150
Hashing 151 => 151
Hashing 152 => 152
Hashing 153 => 153
Hashing 154 => 154
Hashing 155 => 155
Hashing 156 => 156
Hashing 157 => 157
Hashing 158 => 158
Hashing 159 => 159
Hashing 160 => 151
Hashing 161 => 152
Hashing 162 => 153
Hashing 163 => 154
Hashing 164 => 155
Hashing 165 => 156
Hashing 166 => 157
Hashing 167 => 158
Hashing 168 => 159
Hashing 169 => 160
Hashing 170 => 152
Hashing 171 => 153
Hashing 172 => 154
Hashing 173 => 155
Hashing 174 => 156
Hashing 175 => 157
Hashing 176 => 158
Hashing 177 => 159
Hashing 178 => 160
Hashing 179 => 161
Hashing 180 => 153
Hashing 181 => 154
Hashing 182 => 155
Hashing 183 => 156
Hashing 184 => 157
Hashing 185 => 158
Hashing 186 => 159
Hashing 187 => 160
Hashing 188 => 161
Hashing 189 => 162
Hashing 190 => 154
Hashing 191 => 155
Hashing 192 => 156
Hashing 193 => 157
Hashing 194 => 158
Hashing 195 => 159
Hashing 196 => 160
Hashing 197 => 161
Hashing 198 => 162
Hashing 199 => 163
Hashing 200 => 146
Hashing 201 => 147
Hashing 202 => 148
Hashing 203 => 149
Hashing 204 => 150
Hashing 205 => 151
Hashing 206 => 152
Hashing 207 => 153
Hashing 208 => 154
Hashing 209 => 155
Hashing 210 => 147
Hashing 211 => 148
Hashing 212 => 149
Hashing 213 => 150
Hashing 214 => 151
Hashing 215 => 152
Hashing 216 => 153
Hashing 217 => 154
Hashing 218 => 155
Hashing 219 => 156
Hashing 220 => 148
Hashing 221 => 149
Hashing 222 => 150
Hashing 223 => 151
Hashing 224 => 152
Hashing 225 => 153
Hashing 226 => 154
Hashing 227 => 155
Hashing 228 => 156
Hashing 229 => 157
Hashing 230 => 149
Hashing 231 => 150
Hashing 232 => 151
Hashing 233 => 152
Hashing 234 => 153
Hashing 235 => 154
Hashing 236 => 155
Hashing 237 => 156
Hashing 238 => 157
Hashing 239 => 158
Hashing 240 => 150
Hashing 241 => 151
Hashing 242 => 152
Hashing 243 => 153
Hashing 244 => 154
Hashing 245 => 155
Hashing 246 => 156
Hashing 247 => 157
Hashing 248 => 158
Hashing 249 => 159
Hashing 250 => 151
Hashing 251 => 152
Hashing 252 => 153
Hashing 253 => 154
Hashing 254 => 155
Hashing 255 => 156

数値が高くなる傾向に注意してください。それが私たちのデッドフォールであることが判明しました。ハッシュを4回実行すると($ hash = ourHash($ hash) `、各要素に対して)、次のようになります。

Hashing 0 => 153
Hashing 1 => 154
Hashing 2 => 155
Hashing 3 => 156
Hashing 4 => 157
Hashing 5 => 158
Hashing 6 => 150
Hashing 7 => 151
Hashing 8 => 152
Hashing 9 => 153
Hashing 10 => 157
Hashing 11 => 158
Hashing 12 => 150
Hashing 13 => 154
Hashing 14 => 155
Hashing 15 => 156
Hashing 16 => 157
Hashing 17 => 158
Hashing 18 => 150
Hashing 19 => 151
Hashing 20 => 158
Hashing 21 => 150
Hashing 22 => 154
Hashing 23 => 155
Hashing 24 => 156
Hashing 25 => 157
Hashing 26 => 158
Hashing 27 => 150
Hashing 28 => 151
Hashing 29 => 152
Hashing 30 => 150
Hashing 31 => 154
Hashing 32 => 155
Hashing 33 => 156
Hashing 34 => 157
Hashing 35 => 158
Hashing 36 => 150
Hashing 37 => 151
Hashing 38 => 152
Hashing 39 => 153
Hashing 40 => 154
Hashing 41 => 155
Hashing 42 => 156
Hashing 43 => 157
Hashing 44 => 158
Hashing 45 => 150
Hashing 46 => 151
Hashing 47 => 152
Hashing 48 => 153
Hashing 49 => 154
Hashing 50 => 155
Hashing 51 => 156
Hashing 52 => 157
Hashing 53 => 158
Hashing 54 => 150
Hashing 55 => 151
Hashing 56 => 152
Hashing 57 => 153
Hashing 58 => 154
Hashing 59 => 155
Hashing 60 => 156
Hashing 61 => 157
Hashing 62 => 158
Hashing 63 => 150
Hashing 64 => 151
Hashing 65 => 152
Hashing 66 => 153
Hashing 67 => 154
Hashing 68 => 155
Hashing 69 => 156
Hashing 70 => 157
Hashing 71 => 158
Hashing 72 => 150
Hashing 73 => 151
Hashing 74 => 152
Hashing 75 => 153
Hashing 76 => 154
Hashing 77 => 155
Hashing 78 => 156
Hashing 79 => 157
Hashing 80 => 158
Hashing 81 => 150
Hashing 82 => 151
Hashing 83 => 152
Hashing 84 => 153
Hashing 85 => 154
Hashing 86 => 155
Hashing 87 => 156
Hashing 88 => 157
Hashing 89 => 158
Hashing 90 => 150
Hashing 91 => 151
Hashing 92 => 152
Hashing 93 => 153
Hashing 94 => 154
Hashing 95 => 155
Hashing 96 => 156
Hashing 97 => 157
Hashing 98 => 158
Hashing 99 => 150
Hashing 100 => 154
Hashing 101 => 155
Hashing 102 => 156
Hashing 103 => 157
Hashing 104 => 158
Hashing 105 => 150
Hashing 106 => 151
Hashing 107 => 152
Hashing 108 => 153
Hashing 109 => 154
Hashing 110 => 155
Hashing 111 => 156
Hashing 112 => 157
Hashing 113 => 158
Hashing 114 => 150
Hashing 115 => 151
Hashing 116 => 152
Hashing 117 => 153
Hashing 118 => 154
Hashing 119 => 155
Hashing 120 => 156
Hashing 121 => 157
Hashing 122 => 158
Hashing 123 => 150
Hashing 124 => 151
Hashing 125 => 152
Hashing 126 => 153
Hashing 127 => 154
Hashing 128 => 155
Hashing 129 => 156
Hashing 130 => 157
Hashing 131 => 158
Hashing 132 => 150
Hashing 133 => 151
Hashing 134 => 152
Hashing 135 => 153
Hashing 136 => 154
Hashing 137 => 155
Hashing 138 => 156
Hashing 139 => 157
Hashing 140 => 158
Hashing 141 => 150
Hashing 142 => 151
Hashing 143 => 152
Hashing 144 => 153
Hashing 145 => 154
Hashing 146 => 155
Hashing 147 => 156
Hashing 148 => 157
Hashing 149 => 158
Hashing 150 => 150
Hashing 151 => 151
Hashing 152 => 152
Hashing 153 => 153
Hashing 154 => 154
Hashing 155 => 155
Hashing 156 => 156
Hashing 157 => 157
Hashing 158 => 158
Hashing 159 => 159
Hashing 160 => 151
Hashing 161 => 152
Hashing 162 => 153
Hashing 163 => 154
Hashing 164 => 155
Hashing 165 => 156
Hashing 166 => 157
Hashing 167 => 158
Hashing 168 => 159
Hashing 169 => 151
Hashing 170 => 152
Hashing 171 => 153
Hashing 172 => 154
Hashing 173 => 155
Hashing 174 => 156
Hashing 175 => 157
Hashing 176 => 158
Hashing 177 => 159
Hashing 178 => 151
Hashing 179 => 152
Hashing 180 => 153
Hashing 181 => 154
Hashing 182 => 155
Hashing 183 => 156
Hashing 184 => 157
Hashing 185 => 158
Hashing 186 => 159
Hashing 187 => 151
Hashing 188 => 152
Hashing 189 => 153
Hashing 190 => 154
Hashing 191 => 155
Hashing 192 => 156
Hashing 193 => 157
Hashing 194 => 158
Hashing 195 => 159
Hashing 196 => 151
Hashing 197 => 152
Hashing 198 => 153
Hashing 199 => 154
Hashing 200 => 155
Hashing 201 => 156
Hashing 202 => 157
Hashing 203 => 158
Hashing 204 => 150
Hashing 205 => 151
Hashing 206 => 152
Hashing 207 => 153
Hashing 208 => 154
Hashing 209 => 155
Hashing 210 => 156
Hashing 211 => 157
Hashing 212 => 158
Hashing 213 => 150
Hashing 214 => 151
Hashing 215 => 152
Hashing 216 => 153
Hashing 217 => 154
Hashing 218 => 155
Hashing 219 => 156
Hashing 220 => 157
Hashing 221 => 158
Hashing 222 => 150
Hashing 223 => 151
Hashing 224 => 152
Hashing 225 => 153
Hashing 226 => 154
Hashing 227 => 155
Hashing 228 => 156
Hashing 229 => 157
Hashing 230 => 158
Hashing 231 => 150
Hashing 232 => 151
Hashing 233 => 152
Hashing 234 => 153
Hashing 235 => 154
Hashing 236 => 155
Hashing 237 => 156
Hashing 238 => 157
Hashing 239 => 158
Hashing 240 => 150
Hashing 241 => 151
Hashing 242 => 152
Hashing 243 => 153
Hashing 244 => 154
Hashing 245 => 155
Hashing 246 => 156
Hashing 247 => 157
Hashing 248 => 158
Hashing 249 => 159
Hashing 250 => 151
Hashing 251 => 152
Hashing 252 => 153
Hashing 253 => 154
Hashing 254 => 155
Hashing 255 => 156

自分自身を8つの値に絞り込みました...それは悪いことです...にマップさS(∞)れた元の関数S(256)。つまり、への全射関数マッピング$inputを作成しました$output

Surjective関数があるため、入力のサブセットのマッピングが衝突しない(実際には衝突する)とは限りません。

それがここで起こったことです!私たちの機能は悪かったが、それがこれが機能した理由ではない(それが非常に迅速かつ完全に機能した理由である)。

同じことがでも起こりMD5ます。にマップS(∞)S(2^128)ます。実行MD5(S(output))インジェクティブであるという保証はないため、衝突がないことを意味します。

TL / DRセクション

したがって、出力をmd5直接フィードバックすることで衝突が発生する可能性があるため、反復するたびに衝突の可能性が高くなります。ただし、これは直線的な増加です。つまり、の結果セット2^128は減少しますが、重大な欠陥になるほどの速さで大幅に減少するわけではありません。

そう、

$output = md5($input); // 2^128 possibilities
$output = md5($output); // < 2^128 possibilities
$output = md5($output); // < 2^128 possibilities
$output = md5($output); // < 2^128 possibilities
$output = md5($output); // < 2^128 possibilities

繰り返し回数が増えるほど、削減はさらに進みます。

修正

幸いにも、これを修正する簡単な方法があります。次の反復に何かをフィードバックします。

$output = md5($input); // 2^128 possibilities
$output = md5($input . $output); // 2^128 possibilities
$output = md5($input . $output); // 2^128 possibilities
$output = md5($input . $output); // 2^128 possibilities
$output = md5($input . $output); // 2^128 possibilities    

以降の反復は、の個々の値に対して2 ^ 128ではないことに注意してください$input$inputつまり、まだラインに衝突する値を生成できる可能性があるということです(したがって、2^128可能な出力よりはるかに少ない値で解決または共振します)。しかし、一般的なケース$inputは、1ラウンドの場合と同じくらい強力です。

待って、それでしたか?これをourHash()関数でテストしてみましょう。に切り替え$hash = ourHash($input . $hash);、100回の反復:

Hashing 0 => 201
Hashing 1 => 212
Hashing 2 => 199
Hashing 3 => 201
Hashing 4 => 203
Hashing 5 => 205
Hashing 6 => 207
Hashing 7 => 209
Hashing 8 => 211
Hashing 9 => 204
Hashing 10 => 251
Hashing 11 => 147
Hashing 12 => 251
Hashing 13 => 148
Hashing 14 => 253
Hashing 15 => 0
Hashing 16 => 1
Hashing 17 => 2
Hashing 18 => 161
Hashing 19 => 163
Hashing 20 => 147
Hashing 21 => 251
Hashing 22 => 148
Hashing 23 => 253
Hashing 24 => 0
Hashing 25 => 1
Hashing 26 => 2
Hashing 27 => 161
Hashing 28 => 163
Hashing 29 => 8
Hashing 30 => 251
Hashing 31 => 148
Hashing 32 => 253
Hashing 33 => 0
Hashing 34 => 1
Hashing 35 => 2
Hashing 36 => 161
Hashing 37 => 163
Hashing 38 => 8
Hashing 39 => 4
Hashing 40 => 148
Hashing 41 => 253
Hashing 42 => 0
Hashing 43 => 1
Hashing 44 => 2
Hashing 45 => 161
Hashing 46 => 163
Hashing 47 => 8
Hashing 48 => 4
Hashing 49 => 9
Hashing 50 => 253
Hashing 51 => 0
Hashing 52 => 1
Hashing 53 => 2
Hashing 54 => 161
Hashing 55 => 163
Hashing 56 => 8
Hashing 57 => 4
Hashing 58 => 9
Hashing 59 => 11
Hashing 60 => 0
Hashing 61 => 1
Hashing 62 => 2
Hashing 63 => 161
Hashing 64 => 163
Hashing 65 => 8
Hashing 66 => 4
Hashing 67 => 9
Hashing 68 => 11
Hashing 69 => 4
Hashing 70 => 1
Hashing 71 => 2
Hashing 72 => 161
Hashing 73 => 163
Hashing 74 => 8
Hashing 75 => 4
Hashing 76 => 9
Hashing 77 => 11
Hashing 78 => 4
Hashing 79 => 3
Hashing 80 => 2
Hashing 81 => 161
Hashing 82 => 163
Hashing 83 => 8
Hashing 84 => 4
Hashing 85 => 9
Hashing 86 => 11
Hashing 87 => 4
Hashing 88 => 3
Hashing 89 => 17
Hashing 90 => 161
Hashing 91 => 163
Hashing 92 => 8
Hashing 93 => 4
Hashing 94 => 9
Hashing 95 => 11
Hashing 96 => 4
Hashing 97 => 3
Hashing 98 => 17
Hashing 99 => 13
Hashing 100 => 246
Hashing 101 => 248
Hashing 102 => 49
Hashing 103 => 44
Hashing 104 => 255
Hashing 105 => 198
Hashing 106 => 43
Hashing 107 => 51
Hashing 108 => 202
Hashing 109 => 2
Hashing 110 => 248
Hashing 111 => 49
Hashing 112 => 44
Hashing 113 => 255
Hashing 114 => 198
Hashing 115 => 43
Hashing 116 => 51
Hashing 117 => 202
Hashing 118 => 2
Hashing 119 => 51
Hashing 120 => 49
Hashing 121 => 44
Hashing 122 => 255
Hashing 123 => 198
Hashing 124 => 43
Hashing 125 => 51
Hashing 126 => 202
Hashing 127 => 2
Hashing 128 => 51
Hashing 129 => 53
Hashing 130 => 44
Hashing 131 => 255
Hashing 132 => 198
Hashing 133 => 43
Hashing 134 => 51
Hashing 135 => 202
Hashing 136 => 2
Hashing 137 => 51
Hashing 138 => 53
Hashing 139 => 55
Hashing 140 => 255
Hashing 141 => 198
Hashing 142 => 43
Hashing 143 => 51
Hashing 144 => 202
Hashing 145 => 2
Hashing 146 => 51
Hashing 147 => 53
Hashing 148 => 55
Hashing 149 => 58
Hashing 150 => 198
Hashing 151 => 43
Hashing 152 => 51
Hashing 153 => 202
Hashing 154 => 2
Hashing 155 => 51
Hashing 156 => 53
Hashing 157 => 55
Hashing 158 => 58
Hashing 159 => 0
Hashing 160 => 43
Hashing 161 => 51
Hashing 162 => 202
Hashing 163 => 2
Hashing 164 => 51
Hashing 165 => 53
Hashing 166 => 55
Hashing 167 => 58
Hashing 168 => 0
Hashing 169 => 209
Hashing 170 => 51
Hashing 171 => 202
Hashing 172 => 2
Hashing 173 => 51
Hashing 174 => 53
Hashing 175 => 55
Hashing 176 => 58
Hashing 177 => 0
Hashing 178 => 209
Hashing 179 => 216
Hashing 180 => 202
Hashing 181 => 2
Hashing 182 => 51
Hashing 183 => 53
Hashing 184 => 55
Hashing 185 => 58
Hashing 186 => 0
Hashing 187 => 209
Hashing 188 => 216
Hashing 189 => 219
Hashing 190 => 2
Hashing 191 => 51
Hashing 192 => 53
Hashing 193 => 55
Hashing 194 => 58
Hashing 195 => 0
Hashing 196 => 209
Hashing 197 => 216
Hashing 198 => 219
Hashing 199 => 220
Hashing 200 => 248
Hashing 201 => 49
Hashing 202 => 44
Hashing 203 => 255
Hashing 204 => 198
Hashing 205 => 43
Hashing 206 => 51
Hashing 207 => 202
Hashing 208 => 2
Hashing 209 => 51
Hashing 210 => 49
Hashing 211 => 44
Hashing 212 => 255
Hashing 213 => 198
Hashing 214 => 43
Hashing 215 => 51
Hashing 216 => 202
Hashing 217 => 2
Hashing 218 => 51
Hashing 219 => 53
Hashing 220 => 44
Hashing 221 => 255
Hashing 222 => 198
Hashing 223 => 43
Hashing 224 => 51
Hashing 225 => 202
Hashing 226 => 2
Hashing 227 => 51
Hashing 228 => 53
Hashing 229 => 55
Hashing 230 => 255
Hashing 231 => 198
Hashing 232 => 43
Hashing 233 => 51
Hashing 234 => 202
Hashing 235 => 2
Hashing 236 => 51
Hashing 237 => 53
Hashing 238 => 55
Hashing 239 => 58
Hashing 240 => 198
Hashing 241 => 43
Hashing 242 => 51
Hashing 243 => 202
Hashing 244 => 2
Hashing 245 => 51
Hashing 246 => 53
Hashing 247 => 55
Hashing 248 => 58
Hashing 249 => 0
Hashing 250 => 43
Hashing 251 => 51
Hashing 252 => 202
Hashing 253 => 2
Hashing 254 => 51
Hashing 255 => 53

そこラフパターンがまだそこだが、それはノーだ。なお、以上(すでにかなり弱かった)私たちの基本的な機能以外のパターンで。

ことしかし注意してください03、彼らは、単一の実行ではなかったにも関わらず、衝突になりました。これは、私が以前言ったことの応用です(衝突抵抗はすべての入力のセットで同じままですが、特定の衝突ルートは、基礎となるアルゴリズムの欠陥のために開く可能性があります)。

TL / DRセクション

入力を各反復にフィードバックすることにより、前の反復で発生した可能性のある衝突を効果的に解消します。

したがって、md5($input . md5($input));理論的には)と同じくらい強いはずmd5($input)です。

これは重要ですか?

はい。これは、RFC 2898で PBKDF2がPBKDF1を置き換えた理由の1つです。2つの内部ループについて考えてみます。

PBKDF1:

T_1 = Hash (P || S) ,
T_2 = Hash (T_1) ,
...
T_c = Hash (T_{c-1}) 

どこc繰り返し回数は、あるPパスワードで、S塩であります

PBKDF2:

U_1 = PRF (P, S || INT (i)) ,
U_2 = PRF (P, U_1) ,
...
U_c = PRF (P, U_{c-1})

PRFは実際には単なるHMACです。しかし、ここでの目的のために、それだけを言いましょうPRF(P, S) = Hash(P || S)(つまり、2つの入力のPRFは、大まかに言えば、2つを連結したハッシュと同じです)。それはほとんどありませんが、私たちの目的のためです。

したがって、PBKDF2は、PBKDF1が保持Hashしない、基になる関数の衝突耐性を保持します。

すべてをまとめる:

ハッシュを反復する安全な方法を知っています。実際には:

$hash = $input;
$i = 10000;
do {
   $hash = hash($input . $hash);
} while ($i-- > 0);

通常は安全です。

では、なぜそれをハッシュしたいの説明するために、エントロピーの動きを分析しましょう。

ハッシュは無限のセットS(∞)を受け入れ、より小さく、一貫したサイズのセットを生成しS(n)ます。次の反復(入力が戻されると想定)はS(∞)S(n)再びマップされます。

S(∞) -> S(n)
S(∞) -> S(n)
S(∞) -> S(n)
S(∞) -> S(n)
S(∞) -> S(n)
S(∞) -> S(n)

最終出力のエントロピーは、最初の出力とまったく同じであることに注意してください。反復しても「わかりにくくなる」ことはありません。エントロピーは同じです。予測不可能性の魔法の原因はありません(ランダム関数ではなく、疑似ランダム関数です)。

ただし、反復することには利点があります。ハッシュ処理が人為的に遅くなります。そして、それが反復が良い考えになり得る理由です。実際、これは最新のパスワードハッシュアルゴリズムの基本原則です(何かを何度も繰り返し行うと遅くなります)。

スローは良いことです。これは、セキュリティの主な脅威であるブルートフォースと闘うためです。ハッシュアルゴリズムの作成が遅いほど、攻撃者は私たちから盗んだパスワードハッシュを攻撃するために働く必要があります。そしてそれは良いことです!!!


1
$output = md5($output); // < 2^128 possibilities---本当に厳しいのですか<、それとも<=
zerkms 2013

2
@zerkms:厳密には何でもありません。md5()本当に確実に知るには、基礎となる関数(この場合)の非常に具体的な詳細を知る必要があります。しかし、一般的に、それは次のようになります<とない<=私達がセットの大きさについて話している、覚えている... $outputのためのすべての可能な$inputs。したがって、衝突が1つでも発生する場合は<、なので<、より優れたジェネラライザです。
ircmaxell 2013

2
@TomášFejfar問題は一般的な衝突ではなく、厳密な出力セットでの衝突(2 ^ 128出力、それぞれ正確に128ビット幅)に関するものだと思います。それインジェクティブかもしれませんが、私が知る限り、一般的な証明は不可能です(特定のアルゴリズムの衝突の例による証明のみ)。入力が128ビットの場合に入力を返す(それ以外の場合はハッシュを返す)ハッシュ関数について考えてみます。一般的にそれは全射的ですが、その出力が供給されると、それは常に単射的です...それが競合のポイントです
ircmaxell


6
Danとircmaxellの間のその議論がどのように終了したかを確認する必要がないために時間を節約したい人にとって、それはうまく終了しました。
jeromej 2015年

51

はい、再ハッシュにより検索スペースが削減されますが、問題ではありません。効果的な削減は重要ではありません。

再ハッシュはブルートフォースにかかる時間を増加させますが、2回だけ行うことも次善策です。

あなたが本当に望んでいるのは、PBKDF2でパスワードをハッシュすることです。これは、ソルトとイテレーションで安全なハッシュを使用する実証済みの方法です。このSO応答を確認してください。

編集:ほとんど忘れてしまいました-MD5を使用しないでください!!!! SHA-2ファミリー(SHA-256、SHA-384、SHA-512)などの最新の暗号化ハッシュを使用します。


2
@DFTR-同意。bcryptまたはscryptがより良いオプションです。
orip

これらも使用しないでください(SHA-2ファミリー)。また、簡単にクラックされる可能性があります。証拠としてcrackstation.netを確認してください。鍵の導出関数(KDF)ベースの暗号化ハッシュ関数であるscryptまたはPBKDF2を使用する場合。
セオドア2014

3
2016年、Argon2とscryptは誰もが使用するよう努力すべきものです
シルクファイア

10

はい-文字列と一致する可能性のある文字列の数を減らします。

すでに述べたように、ソルトハッシュははるかに優れています。

ここの記事:http : //websecurity.ro/blog/2007/11/02/md5md5-vs-md5/は、なぜそれが同等であるかを証明しようとしますが、ロジックはわかりません。一部には、md5(md5(text))を分析するためのソフトウェアがないと想定していますが、レインボーテーブルを作成するのはかなり簡単です。

md5(text)ハッシュよりもmd5(md5(text))タイプのハッシュの数が少ないため、衝突の可能性が高まって(まだありそうもない確率で)、検索スペースが減少するという私の答えに固執しています。


5

ほとんどの回答は、暗号化やセキュリティの背景がない人々によるものです。そして、彼らは間違っています。可能であれば、レコードごとに固有のソルトを使用します。MD5 / SHA / etcは速すぎて、あなたが望むものの逆です。PBKDF2とbcryptは低速ですが(これで十分です)、ASIC / FPGA / GPUを使用すると無効にできます(最近は非常に手頃です)。したがって、メモリハードアルゴリズムが必要です。scryptと入力します。

これは、ソルトと速度に関する素人の説明です(ただし、メモリハードアルゴリズムについては除きます)。


4

私はこれを実際的な観点から見てみます。ハッカーは何ですか?なぜかというと、ハッシュ関数を使用して目的のハッシュを生成する文字の組み合わせです。

保存するのは最後のハッシュだけなので、ハッカーは1つのハッシュをブルートフォースするだけで済みます。ブルートフォースの各ステップで、目的のハッシュを偶然見つけてしまう確率がほぼ同じだとすると、ハッシュの数は関係ありません。100万回のハッシュ反復を行うことができますが、1行の終わりに破壊するハッシュはまだ1つしかなく、それを破壊する確率は他のハッシュと同じであるため、セキュリティを1ビットも増減しません。

たぶん、以前のポスターは入力が関連していると思います。そうではありません。ハッシュ関数に入力したものが目的のハッシュを生成する限り、正しい入力または正しくない入力を通過できます。

今、レインボーテーブルは別の話です。レインボーテーブルは未加工のパスワードしか保持しないため、すべてのハッシュのすべてのハッシュを含むレインボーテーブルは大きすぎるため、2回のハッシュは適切なセキュリティ対策になる場合があります。

もちろん、私はOPが与えた例のみを考慮しています。ここで、それはハッシュされたプレーンテキストのパスワードです。ユーザー名またはソルトをハッシュに含める場合、それは別の話です。レインボーテーブルはすでに大きすぎて実用的でなく、適切なハッシュが含まれているため、2回のハッシュは完全に不要です。

とにかく、ここではセキュリティの専門家ではありませんが、それは私の経験からわかったものです。


この答えはあらゆる点で間違っています。1.最後から2番目のハッシュを知っていても攻撃者に価値はありません。反復ハッシュへの入力はパスワードであり、パスワードは何度も(1回ではなく)ハッシュされるためです。2.入力スペースはパスワード、出力スペースはハッシュされたパスワードです。一般的なパスワードのスペースは、出力スペースよりもはるかに小さいです。3.無塩のダブルハッシュパスワードのレインボーテーブルは、無塩のシングルハッシュパスワードのレインボーテーブルよりも大きくありません。4.ユーザー名はエントロピーが低く、良い塩はランダムです。5.ソルティングはイテレーションの代わりにはなりません。両方必要です。
Clement Cherlin

3

私が読んだことから、パスワードを数百回または数千回再ハッシュすることが実際に推奨される場合があります。

パスワードをエンコードするのにもっと時間がかかるようにできるなら、パスワードを解読するために攻撃者が多くの推測を実行することはより多くの仕事であるという考えです。これは再ハッシュの利点のようです-それはより暗号学的に安全ではありませんが、単に辞書攻撃を生成するのに時間がかかります。

もちろん、コンピューターは常に高速になるため、この利点は時間とともに減少します(または、反復を増やす必要があります)。


私も別のコメントでこれを述べましたが、 en.wikipedia.org

2

個人的には複数のハッシュに悩まされることはありませんが、ユーザー名(または別のユーザーIDフィールド)とパスワードもハッシュして、同じパスワードを持つ2人のユーザーが同じハッシュを取得しないようにします。また、私はおそらく他の定数文字列も入力文字列に入れて、適切に測定します。

$hashed_password = md5( "xxx" + "|" + user_name + "|" + plaintext_password);

13
実際には、定数ではなく、ユーザーごとにランダムに生成される文字列である必要があります。
リザードに請求する

7
提案されているようにユーザー名を入力すると、一定のシークレットが機能します(操作も簡単です)。それは本質的にランダムなユーザー固有のキーを生成します。
SquareCog 2008

4
一定の秘密の塩は、あいまいさによるセキュリティです。「シークレット」が「xxx」+ユーザー名+パスワードを使用していることに気づいた場合、攻撃者はテーブルに対するデータを必要とせずに攻撃を開始します。
リザードに請求する

8
あいまいさによるセキュリティだとは思いません。ソルトを使用する理由は、複数のmd5ハッシュに対してレインボーテーブルを同時に計算できないためです。「xxx」+パスワード(同じソルト)の1つを作成するのは1回だけです。「xxx」+ユーザー名+パスワードのテーブルを作成することは、ブルートフォースよりも悪いです。
FryGuy 2008

5
@Bill Lizard:「攻撃は、特定のユーザー名を攻撃するために1つの辞書を構築することへと減少します」は、ブルートフォース攻撃(実際には、すべてのハッシュを計算することに加えて、ハッシュを格納する必要があるため)なので、ソルトは機能します。この場合は完全に。
Kornel

2

ハッシュアルゴリズムを使用すると仮定します。rot13を計算し、最初の10文字を取ります。これを2回(または2000回)実行すると、より高速な関数を作成できますが、同じ結果が得られます(つまり、最初の10文字だけを取得します)。

同様に、繰り返しハッシュ関数と同じ出力を提供するより高速な関数を作成することも可能です。したがって、ハッシュ関数の選択は非常に重要です。rot13の例と同様に、ハッシュを繰り返すとセキュリティが向上することはありません。アルゴリズムが再帰的に使用するように設計されているという調査がない場合は、追加の保護が提供されないと想定する方が安全です。

つまり、最も単純なハッシュ関数を除くすべての場合、暗号化の専門家がより高速な関数を計算する必要があるため、暗号化の専門家にアクセスできない攻撃者から保護する場合は、繰り返しハッシュ関数を使用する方が実際には安全です。 。


1

一般に、何かをダブルハッシュまたはダブル暗号化するための追加のセキュリティは提供されません。ハッシュを1回解読できる場合は、もう一度解読できます。ただし、通常、これを行ってもセキュリティは損なわれません。

MD5を使用する例では、おそらくいくつかの衝突の問題があることを知っています。「ダブルハッシュ」は、これに対する保護には役立ちません。同じ衝突が発生しても、最初のハッシュが同じになるため、MD5を使用して2番目のハッシュを取得できます。

これは、「逆MD5データベース」のような辞書攻撃から保護しますが、ソルティングも保護します。

正接では、何かを二重に暗号化しても、実際に使用される2つのキーの組み合わせである別のキーが生成されるため、追加のセキュリティは提供されません。したがって、2つのキーを実際に見つける必要がないため、「キー」を見つけるための労力は倍増しません。ハッシュの結果は通常、元の入力と同じ長さではないため、これはハッシュには当てはまりません。


1
すべて正解ですが、MD5での強い衝突抵抗の妥協の影響は少しバランスが取れていないことに注意したいだけです-暗号ハッシュ関数を使用するほとんどのシナリオは、強い衝突抵抗ではなく、弱い抵抗に依存しています。これらはこの脆弱性の影響を受けません。
SquareCog 2008

1

ダブルハッシュは、クライアントでパスワードをハッシュし、そのハッシュの(別のソルトで)ハッシュをサーバーに保存する場合にのみ意味があります。

そうすれば、誰かがサーバーにハッキングしても(SSLが提供する安全性を無視することになります)、それでも彼はクリアなパスワードを入手することができません。

はい、彼はシステムに侵入するために必要なデータを持っていますが、そのデータを使用してユーザーが持っている外部アカウントを危険にさらすことはできません。そして、人々は事実上すべてに同じパスワードを使用することが知られています。

彼がクリアなパスワードを入手できる唯一の方法は、クライアントにkeygenをインストールすることです-そしてそれはもはやあなたの問題ではありません。

要するに:

  1. クライアントでの最初のハッシュは、「サーバー侵害」シナリオでユーザーを保護します。
  2. サーバーの2番目のハッシュは、誰かがデータベースのバックアップを保持している場合にシステムを保護するのに役立ちます。そのため、彼はそれらのパスワードを使用してサービスに接続できません。

1
+1このような答えが出るのを待っていたのは、クライアントにプレーンテキストのパスワードを保存したくないが、最終的な暗号化されたパスワードをネットワーク経由で送信したくない同じシナリオを考えたからです。 DBとの単純な比較。
マーク

1
Webアプリには役立ちません。サーバーが侵害された場合、サーバーがクライアントに送信するコードも侵害されます。攻撃者はクライアント側のハッシュを無効にし、未加工のパスワードをキャプチャします。
Clement Cherlin

0

サーチスペースの削減に関する懸念は数学的には正しいですが、サーチスペースは、実際に(ソルトを使用する場合)2128の十分な大きさのままです。ただし、パスワードについて話しているため、封筒の裏側の計算によると、可能な16文字の文字列(英数字、大文字小文字の区別、いくつかの記号の投入)の数は約2 ^ 98です。したがって、認識された検索スペースの減少は実際には関係ありません。

それを除けば、暗号的に言えば実際には違いはありません。

「ハッシュチェーン」と呼ばれる暗号プリミティブがありますが、システムの整合性を犠牲にすることなく、使用後に署名キーを開示するなど、いくつかのクールなトリックを実行できるテクニックです。最初のキー配布の問題をきれいに回避できます。基本的に、ハッシュのハッシュの大規模なセットを事前計算します-h(h(h(h ....(h(k))...)))、設定された間隔の後で、n番目の値を使用して署名します。キーを取り出し、キー(n-1)を使用して署名します。これで受信者は、以前のすべてのメッセージを送信したことを確認でき、有効期間が過ぎているため、だれも署名を偽ることはできません。

Billが示唆しているように、数十万回の再ハッシュは、CPUの無駄遣いです。128ビットを壊す人々が心配な場合は、長いキーを使用してください。


1
再ハッシュとは、ハッシュを遅くすることです。これは、パスワードベースの暗号化における主要なセキュリティ機能です。PCKS5およびPBKDF2のリンクを参照してください。
orip 2008

0

この記事のいくつかの回答が示唆しているように、セキュリティが向上する場合と、明らかにセキュリティが低下する場合があります。セキュリティを確実に向上させるより良いソリューションがあります。ハッシュを計算する回数を2倍にする代わりに、ソルトのサイズを2倍にするか、ハッシュで使用するビット数を2倍にするか、その両方を行います。SHA-245の代わりに、SHA-512にジャンプします。


これは質問の答えにはなりません。
トカゲに請求する

1
ダブルハッシュは努力する価値はありませんが、ハッシュサイズを2倍にすることには意味があります。これはもっと価値のあるポイントだと思います。
Stefan Rusek 2008

-1

ダブルハッシュは、攻撃者がほとんどのハッシュを作成するためにテーブルを作成した可能性が高いため、醜いです。ハッシュをソルト化し、ハッシュを混ぜ合わせるのが良いでしょう。ハッシュに「署名」する(基本的にソルト処理する)新しいスキーマもありますが、より安全な方法です。


-1

はい。

のような従来のハッシュ関数の複数の反復を絶対に使用しないでくださいmd5(md5(md5(password)))。で、最高のあなたは、セキュリティにおけるわずかな増加になっされます(この申し出GPU攻撃に対するほとんどの保護のようなスキームを、ちょうどパイプライン、それを。)最悪の場合、あなたが追加したすべての反復を使用してハッシュ空間(したがって、セキュリティ)を削減しています。セキュリティ上、最悪の事態を想定するのが賢明です。

有能な暗号技術者が効果的なパスワードハッシュとして設計し、ブルートフォース攻撃と時空間攻撃の両方に耐えられるパスワードを使用してください。これらには、bcrypt、scrypt、および場合によってはPBKDF2が含まれます。glibc SHA-256ベースのハッシュも使用できます。


-1

私は手足を出し、特定の状況ではそれがより安全であると言います...まだ私に反対投票しないでください!

数学/暗号化の観点から見ると、他の誰かが私よりも明確な説明をしてくれると確信しているため、安全性は低くなります。

ただし、MD5ハッシュの大規模なデータベースが存在し、MD5よりも「パスワード」テキストが含まれる可能性が高くなります。したがって、ダブルハッシュによって、これらのデータベースの有効性が低下します。

もちろん、塩を使用する場合、この利点(欠点?)はなくなります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.