私はTerry Chiaによるソルトの要件について 別の質問 への回答を読んでいましたが、彼/彼女は(とりわけ)ソルトはグローバルに一意である必要があると指定しましたが、いずれにも入りません理由の詳細。これは、「データベースのコンテキストで一意であるだけでなく、そこにあるすべてのデータベースのコンテキストで一意である」と定義されました。たとえば、メールボックスを実験用のサンドボックスWebサイト/データベースのソルトとして使用しています。これらは確かに他のウェブサイトで塩として使用されている可能性があります。
私が理解しているように、ソルトの目的は、「複数の危険にさらされたパスワードハッシュをまとめて解読することは、それぞれを個別に解読することよりも簡単ではない」ことを保証することです(Ilmari Karonen、同じ投稿)。誤解しない限り、私のソルトがデータベース内で一意である限り、この制約は満たされます。
グローバルにユニークな塩を生成することは私には制御できないように思えるため、さらに混乱しています。何百万ものサイトが存在する中で、私の塩が他の誰かのサイトで使用されていないことをどのように保証できるでしょうか?公平を期すために、私はまだランダム塩を生成する方法については調べていません。多分アイデアはそれらがそこにあるサイトの数を考慮しても、別々のデータベースのために生成された重複ソルトが非常にありそうもない十分に大きいプールから作成されるということですか?
私はソルトとしてメールアドレスを使用することに偏っています。これは作業が1ステップ少ないためですが、このアプローチに反対する人の数を考えると、私はおそらく間違っていると認識しています。それに、まだ意味がわからないのになぜ私が間違っているのかについてもっと知りたいのです。
ソルティングの目標は事前計算への抵抗です。
guaranteeソルトはグローバルに一意であることはできませんが、(前述のとおり) Rainbow table を生成できないようにするのに十分なサイズのソルトを生成できます。事前(「十分にユニーク」にする)。
より一般的には、ソルトを作成する方法について質問している場合、独自のハッシュ方式を採用しているように思われますが、これは教育的なものかもしれませんが、一般的には推奨されません。
代わりに、既存のハッシュ(PBDKF2やbcryptなど)を使用してください(または、CBHackingがコメントで適切に示唆しているため、scryptまたはArgon2を使用します)。既存のソルティングメソッド(これで十分です)を自動的に継承するだけでなく、実験はパスワードストレージのベストプラクティスに沿って行われます。
2018-04-03を更新:Steve Thomas(sc00bz)が良い点を示しています here Argon2とscryptは実際にはディフェンダーは、一般に大規模な認証(<0.1秒)と互換性があると見なされている速度で使用され、個々のファイルの暗号化と互換性のある速度(1〜5秒)のディフェンダーにとっては優れています。 (これは、0.1秒から1秒のギャップがおそらく興味深いことを意味し、特定の環境のテストに耐えます)。言い換えると、彼の主張は、Argon2またはscryptを0.1秒未満の速度に調整しようとすると、結果はbcryptがそれらの速度よりもクラックに対して耐性が低いということです。
同じスレッドで、Aaron Toponceもbcrypt(base64(sha-256(password)))
を使用してbcryptの長さ(最大72文字)と事前ハッシュの制限を回避するために 素晴らしい提案をしています (Thomas Porninの同様の答え here も参照)。 base64が必要な理由 これも興味深い -省略しないでください。
したがって、ユースケースがスケーラブルで、クラックに強い認証と高速な認証エクスペリエンスを備えている場合は、bcrypt(base64(sha-256(password)))
がおそらく良いアプローチです。 (そして、bcryptの作業係数を、認証速度ウィンドウ内に収まる最大値に調整する必要があります)。ユーザーが認証を1秒以上待つことを許容できる場合は、Argon2iまたはscryptの方が適している場合があります。また、ハードウェア機能が向上するにつれて、相対的なパフォーマンスが時間とともに変化することに注意してください。新しいハッシュのXか月ごとにbcrypt作業係数を増やすと(Dropboxと同様)、今後の機能に時間をかけて適応できるようになります。
Update 2019-09-01高速なハッシュがクラックされないため、ソルト/ペッパーなしで高速なハッシュを低速なハッシュにラップすることは、最初に高速なハッシュに危険をもたらすことが判明しました別のソース(別のリークなど)からの無塩ハッシュは、ラップされたハッシュに対して一括でテストできますこれらの高速ハッシュを最初にクラックする必要なし。高速のハッシュは、別のジョブではるかに高いレートで攻撃できます。したがって、上記のアドバイスはbcrypt(base64(sha256(password.salt)))
に更新する必要があります。
ランダムな値を生成する代わりに、電子メールアドレスを使用する利点はありません。とにかくランダムなsaltのように保存する必要があります。そうしないと、ユーザーが電子メールアドレスを変更することはできません。
グローバルな一意性は必須ではありません。一意性を保証する必要はありませんが、塩がグローバルに一意であるほど優れています。 128ビットソルト(BCrypt)の可能な組み合わせは3E38です。 1秒あたり1000個のソルトを生成したとしても、重複する確率が50%になるまで約6E8年かかると予想されます。
Royceがすでに述べたように、今日のアルゴリズムはすでにソルトを生成し、結果のハッシュ文字列にプレーンテキストを格納しているため、データベースで特別な処理を行う必要はありません(ハッシュ用の1つのフィールドのみ)。
電子メールアドレスを使用する場合、攻撃者は特定の重要な電子メールのレインボーテーブルを事前に計算する可能性があります。
欠点は実際には致命的ではありませんが、単に利点はありません。それで、より複雑で安全でない方法を選択して塩を生成するのはなぜですか。最新のパスワードハッシュ関数を使用してください。
このトピックは、ソルトがグローバルに一意であることが「必要」であると言うのではなく、そうである場合に最適なセキュリティが達成されることを観察すると、より明確になります。
次の単純な攻撃モデルを考えてみます。攻撃者はn
パスワードエントリを取得し、合計でm
テストを実行するためのリソースを持っています。極端な場合を考えてみましょう:
m
計算はすべてのn
エントリに対してチェックできます。つまり、彼らはテストすることができますm * n
ユーザー/パスワードの仮説。m
の各計算は1つのエントリに対してのみチェックできます。これは、m
ユーザー/パスワードの仮説のみをテストすることを意味します。すべてではないが一部のソルトが重複している場合、攻撃者は、異なるソルトの数に比例して、その間に何かを取得します。ただし、これはソルトの複製でソルティングが壊滅的に失敗することを意味するのではなく、その効果が直線的に低下することを意味します。
十分に大きなランダムソルトは一般に実装が簡単で、無視できる可能性はほとんどありませんがグローバルな一意性を実現できるため、そのようにしない理由はほとんどありません。
ランダムな塩には、別の重要な特性があります。これは、リンクする質問に対する martinstoeckliの回答 が指摘しています。攻撃者は、使用する塩を事前に予測することはできません。電子メールアドレスを使用するという提案は、その基準を満たしていません。