8

私が理解している限りでは、新しいPHP パスワード ハッシュ拡張機能(または一般的には bcrypt) の最も重要な機能の 1 つは、アルゴリズムの速度であり、ブルート フォース攻撃方法が大幅に遅くなります。

それでもある程度の速度で動作し、辞書攻撃や脆弱なパスワードのブルート フォース攻撃には十分であり、[おそらく] 6 文字の英数字よりも短い.

だから私は、それがどのように確かに遅いのか、特に、どのパスワード強度が安全に使用できると考えられているのかを知りたい. パスワードの強度は常にセキュリティと使いやすさのトレードオフであるため、「想像できる限りの強度」は答えではありません。

私は実践者であることに注意してください。したがって、具体的な数字に基づく特定の回答は、不確実な結論を伴う長く風の強い理論的推論よりもはるかに望ましい.

もう少し明確にするために、想定される最悪のシナリオ: ユーザー データベースが盗まれ、誰かがパスワードを解読しようとするでしょう。強い塩のおかげで、レインボーテーブルはオプションではありません. したがって、残っている唯一のベクトルは、辞書攻撃とブルート フォースです。事前に生成されたパスワードをユーザーに提供していると仮定すると、辞書攻撃が排除されます。これが、パスワードの強度が私の唯一の関心事である理由です。

更新:
よく理解されていなかったようです。私にとって、この質問は非常に実用的で、かなり答えやすいものです。そして非常に重要です。

十分なパスワードの強度を判断しないと、この新しいアルゴリズムの使用が疑問視される可能性があります。パスワードがまだ安全でないままあるのに、なぜ良いアルゴリズムを気にする必要があるでしょうか? そのため、新しいハッシュ アルゴリズムを使用するための推奨事項とともに、パスワードの最小強度に関する推奨事項が常に存在する必要があるというのが私の強い信念です。私が知りたいこと。

言い換えれば、ある部分について特定の確実性が存在する場合 - アルゴリズム (「他のものではなく、これを使用してください!」) - 別の部分について確実性があるはずです - 同じレベルの権限で話すことができるパスワードの強度. そうしないと、最も弱い部分が最も強い部分を台無しにしてしまいます。

4

3 に答える 3

36

あなたの質問を明確に理解しているかどうかはわかりませんが、パスワードの強度とそれがブルートフォース攻撃にどのように影響するかに焦点を当てます.

それでもある程度の速度で動作し、辞書攻撃や脆弱なパスワードのブルート フォース攻撃には十分であり、[おそらく] 6 文字の英数字よりも短い.

序章

しばらくの間、ハッシュ アルゴリズム (md5、sha、pbkdf2 bcrypt、scrypt など) を忘れて、最初にパスワードの強度に注目しないようにします。

パスワード強度 ウィキ

これは、推測やブルート フォース攻撃に対するパスワードの有効性の尺度です。通常の形式では、パスワードに直接アクセスできない攻撃者がパスワードを正しく推測するために必要な平均試行回数を推定します。

次のように簡単に計算できます。

ここに画像の説明を入力

エントロピーは、 はパスワードの長さ、はアルファベットのサイズH=Llog2Nで与えられ、通常はビット単位で測定されます。LN

ハッシュ関数

password_hashパスワードには[bcrypt][4]デフォルトで十分ですが、PBKDF2scryptなどのより良い代替手段があり、意味の詳細については、パスワードを安全に保存する方法を参照してください

oclHashcatを使用して、以下を見積もりましょう

+--------+-----------+----------------+
|  HASH  | ESTIMATE  |     BITS/S     |
+--------+-----------+----------------+
| MD5    | 10742M    | 90110427136    |
| BCRYPT | 31M       | 260046848      |
+--------+-----------+----------------+

これは推定値であり、ハードウェアの容量によって異なる場合があることに注意してください

この情報を使用して、別のパスワードをブルート フォースするのにかかる時間を安全に計算できます。

PHP でエントロピーを計算する

$passwords = array(
        "1234",
        "F2A1CC",
        "password",
        "PaSSworD",
        "P4ssw0Rd97",
        "p#aSS*Word14",
        "Dance With Me Tonight" 
);

print("PASSWORD\tLENGTH\tENTROPY\tTIME MD5\tTIME BCRYPT\n");

foreach($passwords as $password ){

    printf("%s\t%s\t%s\t%s\t%s\n", 
        $password, 
        strlen($password), 
        $entropy = calculateEntropy($password), 
        totalTime($entropy, "90110427136"),     // Check with MD5
        totalTime($entropy, "260046848")        // Check with BCrypt
    );
}

出力

+-----------------------+--------+---------+------------+----------------+
|       PASSWORD        | LENGTH | ENTROPY |  TIME MD5  |  TIME BCRYPT   |
+-----------------------+--------+---------+------------+----------------+
| 1234                  |      4 |  13.29  | 1min       | 1min           |
| F2A1CC                |      6 |  24.00  | 1min       | 1min           |
| password              |      8 |  37.60  | 1min       | 1min           |
| PaSSworD              |      8 |  45.60  | 1min       | 1day+          |
| P4ssw0Rd97            |     10 |  59.54  | 2mo+       | 71yr+          |
| p#aSS*Word14          |     12 |  75.86  | 13,479yr+  | 4yr+           |
| Dance With Me Tonight |     21 |  120.29 | 474,250yr+ | 164,335,595yr+ |
+-----------------------+--------+---------+------------+----------------+

csv2table を使用して変換された出力

パスワード クラッカーの CUDA/OpenCL 実装は、GPU で利用可能な膨大な量の並列処理を活用でき、1 秒あたり数十億の候補パスワードでピークに達します。

921600M c/s非常に高速なシステムで並行して行うことができる見積もりをしましょう

T = 966367641600 * 8   
T = 7,730,941,132,800  // bits/sec

使用する

foreach($passwords as $password ){  
    printf("%s\t%s\t%s\t%s\n", 
        $password, 
        strlen($password), 
        $entropy = calculateEntropy($password), 
        totalTime($entropy, "7730941132800")        // Check with Hash
    );
}

出力

+-----------------------+---------+---------+----------+
|       PASSWORD        | LENGTH  | ENTROPY |   TIME   |
+-----------------------+---------+---------+----------+
| 1234                  |       4 | 13.29   | 1min     |
| F2A1CC                |       6 | 24.00   | 1min     |
| password              |       8 | 37.60   | 1min     |
| PaSSworD              |       8 | 45.60   | 1min     |
| P4ssw0Rd97            |      10 | 59.54   | 20hr+    |
| p#aSS*Word14          |      12 | 75.86   | 157yr+   |
| Dance With Me Tonight |      21 | 120.29  | 5,527yr+ |
+-----------------------+---------+---------+----------+

ご覧のとおり、まともな 12 桁が壊れるにはまだしばらく時間がかかります。

使用する機能

// Calculate Password entropy
// Uses H = L Log2 N
// where L is the length of the password and
// N is the size of the alphabet, and it is usually measured in bits
function calculateEntropy($password) {

    // See http://en.wikipedia.org/wiki/Password_strength
    // Entropy per symbol for different symbol sets
    // Missing All extended ASCII printable characters
    // Missing Diceware word list

    // TODO
    // Larger Character Set
    // '/[\!"#$%&\'\(\)\*\+,\-.\/:;<\=>\?\@\[\]^_`\{|\}~]+/' => 32,
    $cases = array(
            "/\s+/" => 1, // Arabic numerals (0–9) (e.g. PIN)
            "/[0-9]+/" => 10, // Arabic numerals (0–9) (e.g. PIN)
            "/[a-z]+/" => 26, // Case insensitive Latin alphabet (a-z)
            "/[A-Z]+/" => 26, // Case insensitive Latin alphabet (A-Z)
            '/[\!\@#$%\?\&\*\(\)_\-\+=~:;.]+/i' => 18  // Other Character
        );

    $L = strlen($password); // Length of password
    $N = 0; // Character Set

    foreach($cases as $regex => $value ){
        if (preg_match($regex, $password)){
            $N += $value;
        }
    }

    // Don't confuse hexadecimal for alpha numeric characters
    // hexadecimal numerals (0–9, A-F) (e.g. WEP keys)
    if (ctype_xdigit($password)){
        $N = 16;
    }

    // Fix pure number cases that might have been changed by hexadecimal
    // Arabic numerals (0–9) (e.g. PIN)
    if (ctype_digit($password)){
        $N = 10;
    }

    // Using H = L Log2N
    // See http://en.wikipedia.org/wiki/Password_strength
    // Random passwords entropy
    $H = $L * log($N, 2);
    return number_format($H, 2);
}

// Claculate Total time it would take
// Using Entropy & froce / s
function totalTime($entropy, $force) {
    bcscale(0);

    // Total Base on entorpy 2^H
    $total = bcpow(2, $entropy);

    // Time Taken per sec on Force
    $ss = bcdiv($total, $force);

    $time = "";
    $parts = [];

    $parts['yr'] = bcdiv($ss, "31104000");
    $parts['mo'] = bcdiv(bcmod($ss, 31104000), 2592000);
    $parts['day'] = bcdiv(bcmod($ss, 2592000), 86400);
    $parts['hr'] = bcdiv(bcmod($ss, 86400), 3600);

    // Clean Year
    // Can really generate large numbers

    $suffix = "";
    $yr = $parts['yr'];
    if (!empty($yr)){
        if (bccomp($yr, "1000000") > 0){
            $parts['yr'] = bcdiv($yr, "1000000"); // Million
            $year = " million ";
        }

        if (bccomp($yr, "1000000000") > 0){
            $parts['yr'] = bcdiv($yr, "1000000000"); // Billion
            $year = " billion ";
        }

        if (bccomp($yr, "1000000000000") > 0){
            $parts['yr'] = bcdiv($yr, "1000000000000"); // Trillion
            $year = " trillion ";
        }
    }

    foreach($parts as $t => $v ){
        if (empty($v)){
            continue;
        }
        $time .= number_format($v, 0) . $suffix . $t . "+";
        break;
    }

    return empty($time) ? "1min" : $time;
}

誤解

パスワードの長さはパスワードのエントロピーと同様に重要です。ほとんどの推奨事項は、パスワードの強度を理解せずにbcrypt、パスワードの複雑さなどを使用するようにユーザーにアドバイスしています

しかし実際には、最も単純なパスワードが最も強力なパスワードになることがよくあります。

ここに画像の説明を入力

ソース| 関連するブログ投稿

だから私は、それがどのように確かに遅いのか、特に、どのパスワード強度が安全に使用できると考えられているのかを知りたい.

ここに画像の説明を入力 ソース

絶対にありません6 letters:)

  • < 28 ビット = 非常に弱い。家族を締め出すかもしれない
  • 28 ~ 35 ビット = 弱い。ほとんどの人を締め出す必要があり、多くの場合、デスクトップのログイン パスワードに適しています
  • 36 ~ 59 ビット = 妥当。ネットワークおよび会社のパスワード用のかなり安全なパスワード
  • 60 ~ 127 ビット = 強力。財務情報を保護するのに適しています
  • 128+ ビット = 非常に強い。しばしばやり過ぎ

結論

ここにあなたが見るべきかもしれないいくつかの良い参考文献があります

于 2014-02-10T04:52:27.120 に答える
3

興味深い質問ですが、最終的な答えを出せる人はほとんどいません。

ご存知のように、BCrypt (およびその他のキー派生関数) にはコスト要因があります。通常、サーバーがパスワードのハッシュに一定の時間 (たとえば 1 ミリ秒) を必要とするまで、このコスト係数を調整します。したがって、同じハードウェアを使用する攻撃者は、1,000 ハッシュ/秒を計算できます。

oclHashcat (GPU)の速度をその CPU バージョンと比較すると、MD5 の係数が 100 であることがわかります。したがって、攻撃者は約 1'000'000 ハッシュ/秒をブルートフォースできると推測できます (BCrypt は GPU に適していませんが、安全側で...)。これは、8'000'000'000 MD5 ハッシュ/秒からの方法であり、コスト要因に依存します。

2 つ目の問題は、パスワードの強度です。一般的な辞書の一部であれば、たとえ長くてもすぐに見つけられるため、最小の長さは強力なパスワードを保証するものではありません。それが十分に「ランダム」である場合、それをクラックする唯一の方法は、総当たり攻撃です (私たちにとって最良のケースです)。この場合、いくつかの計算を試すことができます。

Password alphabet: 62 characters (a-z A-Z 0-9)
Combinations to try: half of all possible combinations
Password length 7: 3E12 combinations → 20 days
Password length 8: 2E14 combinations → 3-4 years

もちろん、これは多くの仮定に基づいています。おそらく、攻撃者はブルート フォース攻撃をはるかに高速に実行できるか、パスワードがそれほど強力ではない可能性があります。私自身は最低 8 文字を要求しますが、パスフレーズを使用することをお勧めします。

編集:パスワードの強度に関するもう1つの注意:

パスワードの強度は、数式ではなく、現実的に計算することはできません。すべての本格的なパスワード クラッカー ツールは、ハイブリッド攻撃とルール ベースの攻撃をサポートします。強力に見えるパスワードは、辞書の一部であるか、ルールによって対処されている場合、非常に弱い可能性があるため、攻撃者の想像力、つまりパスワードをどれだけ速くクラックできるかによって異なります。

私たちが言える唯一のことは、長くてランダムなパスワードは強力であるということです。なぜなら、総当たり攻撃よりも簡単にパスワードを解読する方法はないからです。しかし、これはここでは役に立ちません。Web サイトを構築した開発者ではなく、ユーザーが自分のパスワードを選択し、理想的なパスワードを選択しないためです。

于 2014-02-07T15:38:52.277 に答える