パスワードを複数回ハッシュする方が安全ですか?


43

パスワードを保存するとき、文字列を「ダブルハッシュ」することをお勧めします(たとえば、md5、sha1、両方ともソルトを使用するなど)。

最初の質問は、「これは実際に正しいのですか?」そうでない場合は、この質問の残りを無視してください:)

私が尋ねる理由は、一見すると、これが理にかなっていると言うことです。しかし、それについて考えると、ハッシュが再ハッシュされるたびに(おそらく何かが追加されて)、私が見ることができるのは、最終的な「一意性」の上限が減少していることです...初期入力。

別の言い方をしましょう。ハッシュされたときにy個の可能な文字列に削減されるx個の文字列があります。つまり、最初のセットには衝突があります。今、2番目のセットから3番目のセットに来て、同じことが発生することはできません(つまり、3番目のセットで同じハッシュになるすべての「y」文字列のセットでの衝突)?

私の頭の中では、各ハッシュ関数呼び出しの「ファンネル」、無限の可能性のセットを有限セットに「ファネル化」するなどが見えますが、明らかに各呼び出しはその前の有限セットで動作しており、入力より大きく設定しないでください。

たぶん、例は私のとりとめを説明しますか?「a」と「b」にハッシュ「1」を与え、「c」と「d」にハッシュ「2」を与える「hash_function_a」を取ります。この関数を使用してパスワードを保存すると、パスワードが「a」であっても、パスワード「b」を使用できます。

「1」と「2」にハッシュ「3」を与える「hash_function_b」を取ります。「hash_function_a」の後に「セカンダリハッシュ」として使用する場合、パスワードが「a」であっても「b」、「c」または「d」を使用できます。

それに加えて、ソルトを使用する必要がありますが、「x」入力を「less than x」出力にマッピングするたびに実際に変更されるわけではありません。私はそうは思いません。

誰かが私にここで不足していることを説明してもらえますか?

ありがとう!

編集:それが価値があるため、私は自分でこれを行うのではなく、bcryptを使用します。そして、「ハッカー」にとって「サイクルを使い切る」のに役立つかどうかはあまり心配していません。私は本当に、プロセスがハッシュ衝突の観点から「セキュリティ」を低下させるかどうか疑問に思っています。


2
@ S.Lott:実際の質問にそれがどのように答えるかはわかりませんが、それは...「それを自分でやらないでください」または「時間をかけるのは良いことです」というだけです。 ..どちらの答えも「実際にはより安全ですか」。繰り返しますが、何かが足りない場合を除きます。
水仙

@MetalMikester:ええ、それは昨日の記事でした:thedailywtf.com/Articles/Bulletproof-Encryption.aspx
FrustratedWithFormsDesigner

これはITセキュリティのトピックではありませんが、暗号化に適しているようです。実際、この質問と非常によく似てます。

無塩を使いたい会社を知っていますMD5(password)。安全ではないと言ったので、MD5(MD5(password))代わりに使用することを提案しました...
configurator

受け入れられた答えは正しい答えではありません!
マルクス

回答:


27

これはsecurity.stackexchangeにより適していますが...

の問題

hash1(hash2(hash3(...hashn(pass+salt)+salt)+salt)...)+salt)

これは、チェーン内の最も弱いハッシュ関数と同じくらい強いだけです。たとえば、ハッシュ(最も内側のハッシュ)が衝突する場合、ハッシュチェーン全体が衝突します(チェーン内の他のハッシュに関係なく)。

より強いチェーンは

hash1(hash2(hash3(...hashn(pass + salt) + pass + salt) + pass + salt)...) + pass + salt)

ここでは、早期衝突の問題を回避し、最終ハッシュのパスワードに依存するソルトを本質的に生成します。

また、チェーンの1つのステップが衝突しても、次のステップではパスワードが再び使用され、パスワードごとに異なる結果が得られるため、問題はありません。


だから今、次のラウンドのハッシュにソルトとして「パスワード+ソルト」を追加すると、ファネルに入る可能性のある「もの」の量が増える可能性があることがわかりました。ありがとう。
水仙

実際に私は今それを手に入れたと思う:パスワードをハッシュの各レイヤーに強制することにより、「衝突パスワード」と実際のパスワードに各「呼び出し」で一致するハッシュを持たせることを本質的に要求することにより、起こりうる衝突の数を実際に減らすか、 右?「各レイヤーにパスワードを入力する」部分が欠けていたと思います!再度、感謝します。
水仙

無PROB @Narcissus、それはまた、内側ハッシュがちょうど次のパスのために塩を生成しているように弱い内側ハッシュ(長いアウター/最終ハッシュが強いほど)を可能にするのボーナスを有する
ラチェットフリーク

うーん、問題はそれよりも少し大きい(そして深い)と思います。レインボー攻撃では、すべてのハッシュを考慮してテーブルを生成できますが、問題は残ります。
woliveirajr

4
@Narcissus:非常に短い答え:はい、それはより安全ではありません。はい、おそらくそれはさらに安全ではありません
woliveirajr

54

異なるハッシュアルゴリズムを使用するのは悪い考えです。エントロピーを増加させるのではなく減少させます。

ただし、暗号的に強力なハッシュアルゴリズムと優れたソルトがある場合、同じハッシュ関数を数回適用すると、ハッシュプロセスの計算コストが高くなります。これの利点は、パスワードハッシュをクラッキングする他の手段(推測、辞書攻撃、レインボーテーブルなど)が失敗し、攻撃者がブルートフォース技術を強いられる場合、単純に次の理由で各パスワードの試行に時間がかかることです。同じハッシュ関数をより頻繁に適用する必要があります。したがって、1回のハッシュ処理で1か月のブルートフォースが必要な場合、12回適用すると、推定時間が1年に増加します。

bcryptのような最近のハッシュアルゴリズムは、この考えに基づいています。ハッシュの計算の複雑さを制御するパラメーターが含まれているため、ハードウェアの速度が上がるにつれてそれをスケーリングできます。ハードウェアが2倍速くなると、補償する複雑さが増すため、ブルートフォースに必要な時間はハッシュはほぼ一定のままです。


2
これは正解です!
マルクス

@markus:私が読んだ議論によれば、これは受け入れられた答えによって対処される追加の「そして良い塩」のために正しいだけではありませんか?なぜこれが正しいのか、受け入れられた答えはそうではないのか?
水仙

同じハッシュ関数を複数回適用(パラメーター化)する唯一の理由は、この反復を使用してハードウェアの高速化を調整できるからです。それ以外の場合、複数回ハッシュすることの利点はありません。
マルクス

@Narcissusここで重要なのはエントロピーです。同じメソッドを使用して何度もハッシュすることと、異なるメソッドを使用して何度もハッシュすることには違いがあります。
サキスク

3

暗号化やセキュリティエンジニアリングのコースを受講する意思がない限り、独自のパスワードハッシュスキームを作成しないでください。

パスワードハッシュの確立された実装を使用する必要があります。この実装では、PBKDF2、bcrypt、scrypt、またはより新しいArgon2などのキー派生関数(KDF)を使用する必要があります。

優れたKDFには、オフライン攻撃のコストを増加させるために、通常は何度も反復するワークファクターが含まれます。これらのKDFは、毎回同じアルゴリズムを使用して、パスワードを複数回ハッシュすると言うことができます。他の人が指摘したように、複数のメッセージダイジェストアルゴリズムを使用しても意味がありません。


1
リンクhttps://crackstation.net/hashing-security.htmがファイアウォールによってブロックされている
-gnat

1
@gnat何らかの理由で、ブロックされたURLに関するコメントを逃していました。ウィキペディアへのリンクに置き換えました。
エルワンルグラン

2

一般に、複数のハッシュアルゴリズムを使用する必要はありません。

あなたがする必要があるのは:

saltを使用する:saltはパスワードをより安全にするためだけに使用されるのではなく、レインボーテーブル攻撃を回避するために使用されます。そうすれば、システムに保存するパスワードのハッシュを事前に計算しようとして、誰かがより苦労することになります。

複数の相互作用を使用します:SHA(password + salt)だけを行う代わりに、SHA(SHA(SHA(SHA(SHA(... SHA(password + salt))))))を実行します。または、他の方法で表すには:

hash = sha(password + salt)
for i=1 , i=5000, i++ {
    hash = sha(hash + salt);
}

そして最後に、適切なハッシュ関数を選択します。SHA、MD5などは、すぎるため良くありません。保護にハッシュを使用するため、低速のハッシュを使用することをお勧めします。たとえばBcryptPBKDF2またはScryptを見てください

編集:観察した後、いくつかのポイントを見てみましょう(申し訳ありませんが、最後に到達するための長い説明。

保存されたパスワードに誰もアクセスできないように、システムが安全であれば、ハッシュは必要ありません。パスワードは秘密であり、だれもそれを取得しません。

ただし、パスワードを含むデータベースが盗まれることを保証することはできません。データベースを盗み、すべてのパスワードを取得しました。わかりました、あなたのシステムとあなたの会社はそれのすべての結果に苦しむでしょう。そのため、このパスワードの漏洩を回避することができます。

この時点でオンライン攻撃を心配していないことに注意してください。あるオンライン攻撃の場合、最良の解決策は、不正なパスワードの後に​​速度を落とす、いくつかの試行後にアカウントをロックするなどです。そのため、パスワードを暗号化、ハッシュ、保存などの方法は関係ありません。オンライン攻撃とは、パスワード入力遅くすることです

それでは、don't let them take my plain passwords問題に戻りましょう。答えは簡単です。プレーンテキストとして保存しないでください。はい、わかった。

それを避ける方法は?

パスワードを暗号化します(?)。ただし、ご存知のように、適切なキーがあれば、暗号化すれば復号化できます。そして、あなたはキーを「隠す場所」の問題になってしまいます。彼らはあなたにデータベースを手に入れたので、彼らはあなたの鍵を手に入れることができます。使用しないでください。

そのため、別のアプローチ:パスワードを元に戻せない別のパスワードに変換して保存します。そして、指定されたパスワードが正しいかどうかを確認するために、同じプロセスを再度実行し、変換された2つの値が一致するかどうかを確認します。一致する場合=適切なパスワードが提供されました。

さて、これまでのところとても良い。パスワードにMD5ハッシュを使用してみましょう。しかし...誰かがパスワードのハッシュ値を保存している場合、すべての可能なパスワード(ブルートフォース)のMD5ハッシュを計算するためのコンピューターの能力を十分に持つことができるため、元のパスワードを見つけることができます。または、最悪の場合でも、彼はすべてのキャラクターの組み合わせからすべてのMD5を保存し、パスワードを簡単に見つけることができます。そのため、HASH(HASH(HASH()))のように多くのイテレーションを実行し、より時間がかかるため、難しくします。

しかし、それは回避できますが、レインボーテーブルは、この種の保護に対抗するために正確に作成されました。

それで、その上にいくつかの塩を使用しましょう。この方法では、各相互作用で、塩が再び使用されます。パスワードを攻撃しようとすると、ソルトが毎回追加されることを考慮して、レインボーテーブルを生成する必要があります。そして、彼がそのレインボーテーブルを生成するとき、1つのソルトで生成されたため、彼はもう1つのソルトで再度計算する必要があるので、各パスワード(=各ソルト)にいくらかの時間を費やす必要があります。Saltはパスワードに「複雑さ」を追加しません。それは、攻撃者がレインボーテーブルを生成する時間をゆるめるだけです。パスワードごとに1つのsaltを使用すると、1つのsaltのテーブルは別のパスワードには役に立たなくなります。

そして、ここで複数のハッシュを使用すると役立ちますか?いいえ。特定のレインボー攻撃を生成する人は、とにかく1つ以上のハッシュを使用して生成できます。

また、複数のハッシュを使用すると、1つの問題が発生する可能性があります。使用する最も弱いハッシュと同じくらい安全です。誰かが1つのハッシュアルゴリズムで衝突を見つけた場合、そのハッシュが反復プロセスの任意の時点で悪用されてパスワードが破られます。したがって、より多くのハッシュアルゴリズムを使用しても何も得られません。良いアルゴリズムを1つだけ選択することをお勧めします。そしてそれを使用します。そして、それが壊れていると聞いた場合、アプリケーションでそれをどのように変更するかを考えてください。

そして、なぜbcryptまたはそのようなものを使用するのか(あなたはそれを使用すると言います):攻撃者はテーブルの生成により多くの時間を費やす必要があるからです。そのため、MD5 +待機(3秒)を使用しても役に立たないのです。攻撃はとにかくオフラインになるため、攻撃者は(3秒の遅延なしで)テーブルを生成できます。


2
おっと!申し訳ありませんが、私のコメント(タイムアウトパラメータを使用して意図的にハッシュを遅くすることについて)は、真剣に受け止めるつもりはありませんでした...最近Dilbertを読みすぎていると思います。
FrustratedWithFormsDesigner

2
sha(sha(sha(。。。)))はshaより安全ではありません。sha関数のエントロピーが最大でない場合、これは実際には安全性が低くなります。
deadalnix

1
@deadalnix:元のパスワードを簡単に回復することはできませんが、衝突するパスワードを生成することは簡単になります。これは必要なことです。
ブライアンベッチャー

1
@deadalnix、私はそのコメントをデール・グリブルの声で読んだ。
ジギー

1
@deadalnix:sha(sha(sha()))の目標は、エントロピーを追加することではありません。エントロピーは、最初のユーザーが自分のパスワードを選択することによって作成されます。他のすべて(ハッシュ、ソルトなど)は、ブルートフォース攻撃を遅らせるためのものです。誰かがパスワードを含むデータベースを取得することができた場合、彼はおそらく、任意のハードコードされた塩も知られているように、コードは、同様にパスワードをハッシュするために使用されます
woliveirajr

-1

私の理解は、複数のハッシュアルゴリズムを使用することはレインボーテーブルを打ち負かすことであるということです。良い塩を使用してもうまくいきますが、私はそれが第二レベルの保護だと思います。


4
まあ、これはそれほど変わりません。「複数のハッシュ」機能は1つと見なされ、そのように扱われます。
deadalnix

2
複数のハッシュテクニックまたは反復を使用しても、レインボーテーブルを無効にすることはできません。攻撃者がデータベースを持ち、ハッシュを生成するための方法を使用している場合、攻撃者はレインボーテーブルを生成してデータベース内のすべてのパスワードを攻撃できます。SALTは、たとえば8文字以下のすべてのパスワードを攻撃するための単一のルックアップ辞書を攻撃者が生成することを防ぐため、レインボーテーブル攻撃を防ぎます。
エリック

-1

これは安全ではありません。ただし、同じ関数を使用して、ハッシュに複数回基づいて識別プロトコルを作成します。

これはそのとおりです。格納された値はコンピューターAのhash ^ n(pass)です。AはBに認証を求め、Bに整数nを与えます。Bは計算hash ^(n-1)(pass)を実行し、Aに送り返します。

hash(hash ^(n-1)(pass))== hash ^ n(pass)のチェック。真の場合、認証が行われます。しかし、その後、Aストアhash ^(n-1)(pass)と次の認証は、nの代わりにB n-1を与えます。

これにより、パスワードが明確に交換されないこと、Aがパスワードを知らないこと、および認証がリプレイによって保護されることが保証されます。ただし、これには、有効期間が限られたパスワードが必要という欠点があります。nが値2に達すると、認証後に新しいパスワードを選択する必要があります。

複数のハッシュの別の使用法は、リクエストの認証と整合性を確保するためのツールHMACです。HMACの詳細については、http://en.wikipedia.org/wiki/HMACを参照してください

現実の世界での複数のハッシュのほとんどの使用法は過剰です。あなたの場合、それはそうです。複数のハッシュ関数を使用する場合、それらはすべて同じエントロピーを持たないため、ハッシュの強度が低下することに注意してください。たとえば、md5のエントロピーはsha1よりも小さいため、md5でsha1を使用してもハッシュの強度は向上しません。強度は通常、より弱いハッシュ関数の強度に等しくなります。

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