什么是密码强度,足以与password_hash函数一起使用?

时间:2014-02-06 16:37:24

标签: php security hash bcrypt php-password-hash

据我了解,新PHP password hashing extension(或一般的bcrypt)最重要的功能之一是算法的速度,它大大减慢了暴力攻击方法。

但它仍然以某种速度运行,对于字典攻击来说肯定是足够的,并且强制弱密码,[据说]短于六个字母数字字符。

所以我想知道,它肯定是慢的,特别是哪个密码强度被认为是安全的。 “尽可能强大”并不是一个答案,因为密码强度始终是安全性和可用性之间的权衡 - 所以,我正在寻找可以被认为是安全的甚至是未来证明的最小强度。

请注意我是一个练习者 - 因此,基于具体数字的某些答案比长期且多风的理论推理更为可取,并且结论不确定。

为了澄清一点,最糟糕的情况是:用户数据库被盗,有人会尝试破译密码。由于强盐,彩虹餐桌不是一个选择。 因此,唯一剩下的向量是字典攻击和暴力。假设我们为用户提供预先生成的密码,消除字典攻击。这就是密码强度是我唯一关注的原因。

更新
好像我不太了解。对我来说,问题是实用,并且相当可回答非常重要

如果没有足够的密码强度,可以质疑这种新算法的使用。如果密码仍然不安全,为什么还要用好的算法?所以 - 我坚信 - 除了建议使用新的哈希算法外,还应该始终建议最小密码强度。我想知道。

换句话说,如果某个部分存在特定的确定性 - 算法(“使用这个,而不是其他!”) - 显然应该确定另一个部分 - 密码强度,可以用相同级别的权限说出来。否则最弱的部分会破坏最强的部分。

3 个答案:

答案 0 :(得分:33)

我不确定我是否清楚地理解了您的问题,但我只关注密码强度以及它如何影响暴力攻击。

  

但它仍然以某种速度运行,对于字典攻击来说肯定是足够的,并且强制弱密码,[据说]短于六个字母数字字符。

简介

暂时忘记哈希算法(md5,sha,pbkdf2 bcrypt,scrypt等)并且首先关注Password Strength

密码强度 Wiki

这是衡量密码在抵制猜测和暴力攻击方面的有效性的衡量标准。按照通常的形式,它估计无法直接访问密码的攻击者平均需要多少次试验才能正确猜测。

它可以简单地计算为:

enter image description here

熵由H=Llog2N给出,其中L是密码的长度,N是字母表的大小,通常以位为单位进行测量。

哈希函数

默认情况下,

password_hash使用[bcrypt][4]足以获得密码,但有更好的替代方案,例如PBKDF2scrypt,以获取有关我的意思的更多信息{{ 3}}

使用How To Safely Store A Password,估算以下内容

+--------+-----------+----------------+
|  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+ |
+-----------------------+--------+---------+------------+----------------+

oclHashcat

密码破解程序的CUDA / OpenCL实现可以利用GPU中可用的大量并行性,达到Output Converted using csv2table

让我们估计我们可以在非常快的系统上并行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;
}

误解

你是对的密码长度很重要,所以密码的熵。大多数建议建议用户使用billions of candidate passwords a second,密码复杂性等,而不了解密码强度

但事实是最简单的密码往往是最强的。

enter image description here

use bcrypt | Source

  

所以我想知道,它肯定是慢的,特别是哪个密码强度被认为是安全的。

enter image description here Related blog post

绝对不是6 letters :)

  • &LT; 28位=非常弱;可能会阻止家人
  • 28 - 35位=弱;应该阻止大多数人,通常适合桌面登录密码
  • 36 - 59位=合理;相当安全的网络和公司密码密码
  • 60 - 127位=强;善于保护财务信息
  • 128+位=非常强;经常矫枉过正

结论

以下是一些很好的参考资料,您可以查看

答案 1 :(得分:3)

这是一个有趣的问题,尽管任何人都不太可能给出最终答案。

如您所知,BCrypt(以及其他密钥派生函数)具有成本因素。通常,您会调整此成本因子,直到您的服务器需要一定时间来散列密码,例如1毫秒。因此,具有相同硬件的攻击者可以计算1000赫兹/秒。

如果将oclHashcat(GPU)的速度与其CPU版本进行比较,您会看到MD5的因子为100,因此我们可以猜测攻击者可以强制执行大约1 000'000哈希/秒(BCrypt是不是GPU友好,但为了安全起见...)。这是从8'000'000'000 MD5哈希/ s的方式,并取决于成本因素。

第二个问题是密码的强大程度。如果它是常用字典的一部分,即使它很长也可以快速找到它,因此最小长度不能保证强密码。如果它足够“随机”,那么破解它的唯一方法就是暴力破解(对我们来说是最好的情况)。对于这种情况,我们可以尝试一些数学:

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个字符,但建议使用密码短语。

编辑:关于密码强度的另一个注意事项:

密码的强度无法实际计算,当然不能通过公式计算。每个严肃的密码破解工具都将支持混合攻击和rule based attacks。看起来很强的密码可能非常弱,如果它们是字典的一部分或者是由规则应对,那么它取决于攻击者的想象力,密码被破解的速度有多快。

我们唯一能说的是,长而随机的密码很强,因为没有比暴力破解更容易破解它们的方法。但这在这里没有用,因为用户会选择他们的密码,而不是建立网站的开发者,而且他们不会选择理想的密码。

答案 2 :(得分:0)

根据您的最新评论,您希望构建一个主要政府可接受的密码方案。这些信息随时可用。