web-dev-qa-db-ja.com

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

私は、パスワードを保存するときに文字列を「ダブルハッシュ」することをお勧めします(例:md5を使用してからsha1を使用して両方ともソルトを使用すること)。

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

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

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

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

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

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

さらに、ソルトを使用する必要があることはわかりますが、「x」入力を「x未満」出力にマッピングするたびにソルトを使用しても、実際には変わりません。私は思いません。

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

ありがとう!

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

43
Narcissus

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

の問題

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

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

より強いチェーンは

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

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

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

27
ratchet freak

異なるハッシュアルゴリズムを使用することは悪い考えです。エントロピーを増やすのではなく減らします。

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

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

55
tdammers

暗号化やセキュリティエンジニアリングのコースを進んで受けようとしない限り、独自のパスワードハッシュスキームを記述しないでください。

PBKDF2、bcrypt、scrypt、または新しいArgon2などのキー導出関数( [〜#〜] kdf [〜#〜] )を使用する必要のある、確立されたパスワードハッシュの実装を使用する必要があります。 。

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

3
Erwan Legrand

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

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

ソルトを使用する:ソルトはパスワードを作成するためだけに使用されるわけではありませんより安全、レインボーテーブル攻撃を回避するために使用されます。そうすれば、システムに保存したパスワードのハッシュを事前に計算しようとすると、誰かがもっと大変な仕事をするようになります。

複数の相互作用を使用します。SHA(パスワード+ salt)だけを実行する代わりに、SHA(SHA(SHA(SHA(SHA(... SHA(パスワード+ salt)))))))を実行します。または、別の方法で表すには:

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

そして最後に、適切なハッシュ関数を選択します。 SHA、MD5などは、あまりにも優れているため、よくありませんfast。保護のためにハッシュを使用したいので、遅いハッシュを使用する方がよいでしょう。たとえば、 BcryptPBKDF2 または Scrypt を見てください。

edit:観察後、いくつかのポイントを見てみましょう(他の人が同様の答えを探すのに役立つ可能性があるため、最後に到達するには申し訳ありませんが、長い説明です) :

システムが安全である場合、格納されたパスワードに誰もアクセスすることはないため、ハッシュは必要ありません。パスワードは秘密にされ、だれもそれを入手することはありません。

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

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

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

それを避ける方法は?

パスワードを暗号化します(?)しかし、ご存じのように、適切な鍵があれば、暗号化すれば復号化できます。そして、あなたはキーを「どこに隠すか」という問題に終わるでしょう。うーん、だめです。データベースを入手したので、キーを取得できます。使用しないでください。

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

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

しかし、それを回避することもできますが、レインボーテーブルは、この種の保護に対する速度を上げるために作成されました。

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

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

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

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

2
woliveirajr