私はソルトハッシュについて多くの議論があることを知っています。その目的は、すべての可能なハッシュ(通常は最大7文字)のレインボーテーブルを作成することを不可能にすることであることを理解しています。
私の理解では、ランダムなソルト値は単にパスワードハッシュに連結されるだけです。レインボーテーブルをパスワードハッシュに対して使用できず、ランダムソルトハッシュであることがわかっている最初のXビットを無視できるのはなぜですか?
更新
返信ありがとうございます。これが機能するには、ディレクトリ(LDAPなど)が各ユーザーに固有のソルトを格納する必要があるか、ソルトが「失われ」、認証が発生しないように思われます。
通常は次のように機能します。
あなたのパスワードが「野球」だとしましょう。私はそれをそのまま保存することもできますが、私のデータベースを取得する人はだれでもパスワードを取得します。したがって、代わりにSHA1ハッシュを実行して、これを取得します。
$ echo -n baseball | sha1sum
a2c901c8c6dea98958c219f6f2d038c44dc5d362
理論的には、SHA1ハッシュを元に戻すことは不可能です。しかし その正確な文字列でのグーグル検索 を行えば、元のパスワードを回復するのに問題はありません。
さらに、データベース内の2人のユーザーが同じパスワードを持っている場合、それらは同じSHA1ハッシュを持ちます。そして、そのうちの1つにtry "baseball"
という パスワードヒント がある場合---さて、私は両方のユーザーのパスワードを知っています。
したがって、ハッシュする前に、一意の文字列を付加します。 秘密ではなく、ただユニークなもの。 WquZ012C
はどうですか。これで、文字列WquZ012Cbaseball
をハッシュしています。それはこれへのハッシュです:
c5e635ec235a51e89f6ed7d4857afe58663d54f5
その文字列をグーグルしても何も起こらない(おそらくthisページを除く)ので、今は何かに取り掛かっています。また、person2もパスワードとして「野球」を使用している場合は、別のソルトを使用して別のハッシュを取得します。
もちろん、パスワードをテストするには、塩が何であるかを知っている必要があります。それをどこかに保存する必要があります。ほとんどの実装では、ハッシュを使用して、通常はデリミタを使用してハッシュを直接処理します。 openssl
がインストールされている場合は、これを試してください。
[tylerl ~]$ openssl passwd -1
Password: baseball
Verifying - Password: baseball
$1$oaagVya9$NMvf1IyubxEYvrZTRSLgk0
これにより、標準のcrypt
ライブラリを使用したハッシュが得られます。したがって、ハッシュは$1$oaagVya9$NMvf1IyubxEYvrZTRSLgk0
です。実際には、$
で区切られた3つのセクションです。視覚的にわかりやすくするために、区切り文字をスペースに置き換えます。
$1$oaagVya9$NMvf1IyubxEYvrZTRSLgk0
1 oaagVya9 NMvf1IyubxEYvrZTRSLgk0
プロセスを再度実行すると、異なるソルトで完全に異なるハッシュが得られます。この例では、約1014 この1つのパスワードを保存する方法。これらはすべて「baseball」というパスワード用です。
$1$9XsNo9.P$kTPuyvrHqsJJuCci3zLwL.
$1$nLEOCtx6$uSnz6PF8q3YuUhB3rLTC3/
$1$/jZJXTF3$OqDuk8T/cEIGpeKWfsamf.
$1$2lC.Cb/U$KR0jkhpeb1sz.UIqvfYOR.
しかし、チェックしたいソルトを意図的に指定すると、期待した結果が返されます。
[tylerl ~]$ openssl passwd -1 -salt oaagVya9
Password: baseball
Verifying - Password: baseball
$1$oaagVya9$NMvf1IyubxEYvrZTRSLgk0
これが、パスワードが正しいかどうかを確認するために実行するテストです。ユーザーの保存されたハッシュを見つけ、保存されたソルトを見つけ、保存されたソルトを使用して同じハッシュを再実行し、結果が元のハッシュと一致するかどうかを確認します。
明らかに、この投稿は実装ガイドではありません。 MD5を単純に塩漬けにしないでください。今日のリスク環境ではそれだけでは不十分です。代わりに、ハッシュ関数を数千回実行するiterativeプロセスを実行する必要があります。これは 他の場所で説明されています 何度も繰り返されているため、ここでは "なぜ"については説明しません。
これを行うには、いくつかの確立された信頼できるオプションがあります。
crypt:上記で使用した関数は、unix crypt
パスワードハッシュメカニズムの古いバリエーションです。すべてのUnix/Linuxオペレーティングシステムに。元の(DESベースの)バージョンは恐ろしく安全ではありません。それさえ考慮しないでください。私が示したもの(MD5ベース)はより良いですが、それでも今日は使用すべきではありません。 SHA-256およびSHA-512のバリエーションを含む、その後のバリエーションは妥当なはずです。最近の亜種はすべて、複数ラウンドのハッシュを実装しています。
bcrypt:上記のcrypt
関数呼び出しのフグのバージョン。 blowfishには非常に高価なキーセットアッププロセスがあるという事実を利用し、それに応じてキーセットアップ時間を増加させる「コスト」パラメーターを使用します。
PBKDF2:( "Password-based Key Derivation Function version 2")単純なパスワードから強力な暗号鍵を生成するために作成され、これ 実際にはRFCがある である、ここにリストされている唯一の関数です。設定可能な数のラウンドを実行し、各ラウンドでパスワードと前のラウンドの結果をハッシュします。最初のラウンドは塩を使用します。本来の目的は強力なキーを作成することであり、パスワードを保存することではありませんが、目標の重複によりこれはうまくいきます-ここでも信頼できるソリューション。利用可能なライブラリがなく、何かを最初から実装せざるを得なかった場合、これが最も簡単で最も文書化されたオプションです。しかし、もちろん、入念に吟味されたライブラリを使用することが常に最善です。
scrypt:専用ハードウェアに実装するのが難しいように特別に設計された、最近導入されたシステム。 scryptは、ハッシュ関数の複数ラウンドを必要とするだけでなく、非常に大きな作業メモリ状態を持ち、RAM非常に新しく、ほとんどが証明されていませんが、少なくとも他のセキュリティと同じくらい安全に見え、おそらくそれらすべての中で最も安全です。
技術的には、レインボーテーブルを使用してソルトハッシュを攻撃できます。しかし、技術的にのみ。ソルトハッシュは、クリプトマジックを追加するのではなく、衝突を正常に検出するために必要なRainbowテーブルのサイズを指数関数的に増加させることによって、Rainbowテーブルの攻撃を無効にします。
そして、はい、塩を保存する必要があります:)
ハッシュの後には追加されません。ハッシュの前に追加されるため、ハッシュはソルトごとに完全に異なります。
そうではない
hash abcd = defg
store 123defg (for user with 123 salt) and 456defg (for user with 456 salt)
です
hash 123abcd = ghij
hash 456abcd = klmn
パスワードハッシュの場合、 PBKDF2/RFC2898/PKCS5v2 、Bcrypt、またはScryptのようなものを使用する必要があります。これらはすべて、1回ではなく反復回数(「作業係数」)を選択できます。 。たとえばPBKDF2は、内部的に [〜#〜] hmac [〜#〜] 既知のハッシュアルゴリズム(通常はSHA-512、SHA-256、またはSHA-1)を使用したキー付きハッシュを使用します。繰り返しの数、できれば数十から数十万の高さで、基本的にユーザーが文句を言わずにそれを保つことができます。
反復回数が多い理由は、攻撃者の速度を落とすことです。これにより、攻撃者が一定期間に通過できるキースペースが減少し、より適切なパスワードを効果的に攻撃できなくなります。 「パスワード」と「P @ $$ w0rd」は、明らかにオフライン攻撃に関係なくクラックされることになります。
正解です。各行(ユーザー)には、独自に生成された、暗号的にランダムな長いソルトが必要です。そのソルトはプレーンテキスト形式で保存されます。
PBKDF2、Bcrypt、またはScryptでは、反復回数(作業係数)もデータベースにプレーンテキストで保存することをお勧めします。これにより、変更が簡単になります(個人的には、いくぶんランダム化された反復回数を使用します-常に異なる場合) 、その後、「ああ、いいえ、小さな変更ですべてが台無しになる可能性があります-これ以上変更しないでください」という恐れは、経営陣や他の開発者からはありません)
パスワードハッシュにPBKDF2を使用する場合は、ネイティブハッシュ出力よりも大きな出力を要求しないでください。SHA-1の場合は20バイト、SHA-512の場合は64バイトです。
2つの異なる塩を使用したPBKDF2の実際の例を示します。
(PBKDF2 HMACパスワードソルト反復出力バイトの結果)
タイラーが言ったことに加えて、現代の暗号では、塩はレインボーテーブルからの保護に使用されていないことを強調することが重要です。 Rainbowテーブルを実際に使用する人はいません。本当の危険は並列化です:
そして、それが静的であるかどうかに関係なく、ソルトが広く使用されていない限り、準備されたRainbowテーブルからあなたを保護しますが、ユニークなハッシュごとのソルトのみが、多くの並列計算能力を使用してすべてをクラックするという本当の危険からあなたを保護しますすぐに。
複数のユーザーが同じパスワードを持っている場合、ハッシュが異なるため、より安全です。
Pythonを使用した簡単な実装:
import hashlib
passwordA = '123456'
passwordB = '123456'
hashlib.md5(passwordA).hexdigest()
'e10adc3949ba59abbe56e057f20f883e'
hashlib.md5(passwordB).hexdigest()
'e10adc3949ba59abbe56e057f20f883e'
そして塩を加えましょう:
saltA = 'qwerty'
salbB = 'asdfgh'
passA = passwordA + saltA
passB = passwordB + saltB
hashlib.md5(passA).hexdigest()
'086e1b7e1c12ba37cd473670b3a15214'
hashlib.md5(passB).hexdigest()
'dc14768ac9876b3795cbf52c846e6847'
これは非常に簡略化されたバージョンです。塩は好きな場所に追加できます。パスワードの最初/中間/終わり。
特に多くのユーザーがいて、それぞれのハッシュが異なる場合は、Saltは非常に便利です。 FacebookやGoogle、Twitterアカウントなど、100万のアカウントで同じパスワードを使用する確率を想像してみてください。
まず、2人のユーザーがやや弱いパスワード「野球」を使用している場合、1つのパスワードをクラックしてもソルトのために2番目のパスワードをクラックしてもまったく役に立ちません。塩漬けなしでは、1つの価格で2つのパスワードを解読しました。
次に、レインボーテーブルには、事前に計算されたハッシュが含まれています。そのため、クラッカーは、虹のテーブルで「野球」のハッシュを膨大な数のエントリで検索することができます。レインボーテーブルのガジリオンハッシュを計算するよりもはるかに高速です。そしてそれは塩漬けによって防がれます。
そして今重要なのは、良いパスワードを持っている人もいれば、悪いパスワードを持っている人もいます。 100万人のユーザーがいて、3人が同じパスワードを使用している場合は、knowそのパスワードは脆弱です。ソルトしないと、3つの同一のハッシュになります。したがって、誰かがハッシュのデータベースを盗んだ場合、彼らはすぐにどのユーザーが弱いパスワードを持っているかを確認し、それらの解読に集中できます。 1keOj29fa0romnよりも「野球」をクラックする方がはるかに簡単です。ソルトしないと、弱いパスワードが目立ちます。ソルティングを使用すると、クラッカーはどのパスワードが脆弱で、どのパスワードが解読されにくいかを理解できません。
ハッシュがソルトされているかどうかは、攻撃者がパスワードハッシュを持っている場合にのみ違いを生みます。ソルトがなければ、ハッシュはレインボーテーブル(パスワードをハッシュに関連付ける事前計算済みの辞書)で攻撃される可能性があります。 Nビットソルトは、Rainbowテーブルのストレージ要件と、そのテーブルを計算する時間を2 ** N倍に増やします。したがって、たとえば、32ビットのソルトを使用する場合、たとえばpassw0rd
というパスワードの1つのRainbowテーブルディクショナリエントリは、数ギガバイトのストレージを必要とするため、現在のストレージハードウェアを使用すると、このようなRainbowテーブルは非常に高価になります。そのため、ソルトが存在する場合、攻撃者は取得した特定のパスワードハッシュセットに対するブルートフォース攻撃に限定されます。
しかしながら:
ユーザーjoewestlake
がパスワードgod1234
を使用するとします。攻撃者は、レインボーテーブルを使用して即座にこれを元に戻します。 (または、ハッシュがソルトされている場合、パスワードが非常に悪いため、ブルートフォース攻撃を使用してたった数分で解読できます。)ここで問題は、joewestlake
がGmailアカウントにgod1234
も使用したことです、そしてオンラインバンキングのために、おっと!これで攻撃者はジョーの電子メールを読み、ジョーについて十分に学習して、ジョーのオンラインバンキングにログインするときに「最初のペットの名前は何でしたか」という質問に簡単に答えられるようにします。
したがって、ソルトの理論的根拠は、中程度のセキュリティのパスワードを元に戻すのを難しくすることによって、ユーザーを保護することです。ソルトなしでは、合理的になり得るパスワードレインボーテーブルで見つかると予想されますが、個別にブルートフォースするのに非常に長い時間がかかるほど強力です。しかし、ソルトは、ハッシュが危険にさらされた場合にのみこの利点を提供します。これは、すでに重大なセキュリティ違反であり、この利点は、他のシステムで中程度のセキュリティパスワードを再利用するユーザーにのみあります。
代わりに、ジョーは10個のランダムな英数字と記号で構成されるパスワードを使用しました。これはまだRainbowテーブルにある可能性がありますが、多くの作業が必要です。したがって、ジョーがGmailとオンラインバンキングに同じパスワードを使用したとしても、ソルトのおかげで彼は安全です。クラッカーは彼のブルートフォースクラックをおそらく数時間、おそらく数日間実行します。このクラックは、同じシステムの他のユーザーから弱いパスワードを持っている多数の弱いパスワードを生み出します。攻撃者はその利回りに満足し、クラッキングを停止します。 Joeのパスワードは決して取り消されません。
さらに、違反が検出され、ユーザー(ジョーを含む)がパスワードを変更するように助言された場合、ジョーのパスワードを含む中程度のセキュリティパスワードスペース全体を攻撃者が引き続き攻撃していても、ジョーは攻撃者のクラッキングの試行を追い越す可能性があります。 。 Joeは、侵害されたシステムで使用したパスワードは、Gmailと銀行のパスワードとまったく同じであることを知っているため、他の2つを変更するためにスクランブルをかけます。ソルトは、パスワードを再利用するユーザーがパスワードを変更する時間を稼ぐため、ここで役立ちます。 saltは、数分で解読される非常に弱いパスワードを使用するユーザーには役立ちませんが、解読に数時間または数日かかるパスワードのユーザーには、戦いのチャンスがあります。