web-dev-qa-db-ja.com

なぜ私たちが推奨するのは、常に `HASH(salt + password)`なのですか?

このサイト、多くのフォーラム、オンライン記事を閲覧すると、パスワードハッシュを保存するために提案する特定の方法が常に1つあります。

function (salt, pass) {
   return ( StrongHash(salt + pass) )
}

しかし、なぜこれがexactなのか?なぜこれを行うことを提案しないのですか?

function (salt, pass) {
   return (StrongHash(( StrongHash(salt) + StrongHash(pass) ))
}

それともこのようなものですか?

function (salt, pass) {
   var data = salt + pass;
   for (i=0;i < 1000; i++ {
       data += StrongHash(salt + data)
   }
   return (data)
}

または他のクレイジーな組み合わせ?生のソルトと生のパスワードの連結をハッシュすると具体的になぜ言っているのですか?ハッシュされている両方のハッシュは、私の3番目の例のように1000回ハッシュするのと同じように、かなり高いエントロピーの代替手段のようです。エントロピーのために、最初のハッシュを数回ハッシュしてみませんか?

最初の方法の何がそれほど素晴らしいのですか?


リクエストにより、この例:

  1. http://www.codinghorror.com/blog/2007/09/Rainbow-hash-cracking.html
  2. パスワードハッシュ:ソルト+コショウを追加するか、塩で十分ですか?
  3. ハッシュのストレッチ、多くの反復と長い入力文字列
  4. http://www.aspheute.com/english/20040105.asp
  5. http://phpsec.org/articles/2005/password-hashing.html
  6. http://msdn.Microsoft.com/en-us/library/aa545602.aspx#Y9
  7. http://www.developerfusion.com/article/4679/you-want-salt-with-that/3/
  8. http://ca3.php.net/manual/en/function.hash.php#101987
  9. http://ca3.php.net/manual/en/function.hash.php#89568
22
Incognito

実際、「私たち」はnot提示するものをすべて推奨しています。通常の推奨事項は PBKDF2bcrypt またはLinuxで現在使用されているSHA-2ベースの nix crypt です。

If使用するハッシュ関数は完璧です ランダムOraclethenソルトとパスワードをどのように入力しても問題ありません。重要なのはtimeソルトとパスワードの処理にかかる時間であり、辞書検索を抑止するために、その時間を長くする必要があります。したがって、複数の反復の使用。 ただし、完全にランダムなOracleであることはハッシュ関数にとって難しい特性です。安全なハッシュ関数が提供しなければならない通常のセキュリティプロパティ(衝突やプリイメージへの耐性)によって暗示されることはなく、広く使用されている一部のハッシュ関数はランダムオラクルではないことが知られています。例えばSHA-2関数は、いわゆる「長さ拡張攻撃」の影響を受けます。これにより、安全性が低下することはありませんが、ファンキーなパスワードハッシュスキームで関数を使用するときに注意が必要です。そのため、PBKDF2はしばしば [〜#〜] hmac [〜#〜] とともに使用されます。

notは、パスワードハッシュスキームや暗号化全般についてクリエイティブに感じることを心から勧めています。セキュリティは、微妙で、自分でテストできない詳細に依存しています(テスト中、安全でない関数は安全な関数と同じように機能します)。

43
Thomas Pornin

提案された2つについて-

function (salt, pass) {    return
    (StrongHash( StrongHash(salt) + StrongHash(pass) ) 
}

ここにはボーナスはありません。ハッシュは情報をランダムなものにレンダリングします。したがって、最初のパスでは、2つのデータを2つのランダムな文字列にしてから、2つのランダムな文字列を結合しました。どうして?あいまいさによるセキュリティは何のメリットもありません。一般的に提案されているソリューションの重要な要素は次のとおりです。

  • ソルトとパスワードを組み合わせて、ソルトがパスワードのハッシュを作成するための追加のカオス要素を提供できるようにします
  • ある方法では、集合体をハッシュして、ランダムに見える文字列を作成します。

ランダムよりランダムにすることはできません。セキュリティを確保するために、目的のない作業を回避することをお勧めします。

function (salt, pass) {
   var data = salt + pass;
   for (i=0;i < 1000; i++ {
       data += StrongHash(salt + data)
   }
   return (data)
}

ここで最初に起こることは、データにソルトとパスワードが与えられることです。したがって、出力は次のようになります。

<Salt><Password><randomString0><randomString1>....<randomString999>

<Salt> = the salt in cleartext
<Password> = the password in cleartext
<randomString> = a series of different random strings.

記述されたコードはパスワードを公開しただけなので、ランダムな文字列はすべて意味がありません。

この問題の修正は次のとおりです。

function (salt, pass) {
   var data = salt + pass;
   for (i=0;i < 1000; i++ {
       data = StrongHash(salt + data)
   }
   return (data)
}

+ =の削除に注意して、単純な割り当てに変更してください。これは小さな変更ですが、最終的なデータは、ハッシュアルゴリズムが出力する長さの単一のランダムな文字列になります。

これはおそらくセキュリティの観点からは問題ありませんが、元の単純なバージョンよりも実際には改善されていません。多くの再帰的ハッシュの繰り返しはセキュリティを追加しません-ハッシュアルゴリズムでの最初のパスはランダムな結果を生成するはずです。同じことを何度も繰り返しハッシュしても、最良のケースでは何も行われず、最悪の場合、ハッシュアルゴリズムの値が減少する可能性があります。

最初の方法は非常に重要な利点を提供します-KISSプリンシパル。シンプルにしてください。関数を繰り返しても利益が得られない場合、ロジックをより複雑にし、処理時間を長くし、よりオープンにする理由はありません。エラーになり、デバッグが難しくなります。

また、-暗号化では、すべてのアルゴリズムに、平均的なキュービクルを満たすユーザーマニュアルが付属している必要があります。弱い鍵、繰り返しの問題、露出、その他の数学的入出力の議論についての議論は、数学者に残りの永遠の論文トピックを蓄え続けます。特定のアルゴリズムが機能するまでは、実際の影響を議論することは困難ですが、繰り返しや順列を手助けしようとするのではなく、アルゴリズムの設計に任せるのが一般に良い方針です。多くのハッシュアルゴリズムには、繰り返しと再帰のサイクルがすでにあります。つまり、ユーザーがこれ以上行う理由はありません。

9
bethlakshmi