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

You*_*nse 7 php security hash bcrypt php-password-hash

据我所知,新的PHP密码散列扩展(或一般的bcrypt)最重要的特性之一是算法的速度,这大大减慢了暴力攻击方法.

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

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

请注意我是一个实践者 - 所以,基于具体数字的某些答案比长期和多风的理论推理更为可取,结论不确定.

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

更新:
似乎我不太了解.对我来说,这个问题非常实用,而且相当负责.而且非常重要.

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

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

Bab*_*aba 33

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

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

介绍

暂时忘记哈希算法(md5,sha,pbkdf2 bcrypt,scrypt等)并且首先关注密码强度

密码强度 维基

这是衡量密码抵御猜测和暴力攻击的有效性的指标.以其通常的形式,它估计有多少次试验无法直接访问密码的攻击者平均需要正确猜测它.

它可以简单地计算为:

在此输入图像描述

熵由密码长度H=Llog2N在何处给出,L并且N是字母表的大小,通常以位为单位进行测量.

哈希函数

password_hash使用[bcrypt][4]默认使用是足够了密码,但也有诸如更好的选择PBKDF2scrypt的详细信息,我的意思看如何安全存放密码

使用oclHashcat,我们估计以下内容

+--------+-----------+----------------+
|  HASH  | ESTIMATE  |     BITS/S     |
+--------+-----------+----------------+
| MD5    | 10742M    | 90110427136    |
| BCRYPT | 31M       | 260046848      |
+--------+-----------+----------------+
Run Code Online (Sandbox Code Playgroud)

请注意,这是一个估计,可能会根据硬件容量而有所不同

通过这些信息,我们可以安全地计算出我们需要多长时间才能强制使用不同的密码

在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
    );
}
Run Code Online (Sandbox Code Playgroud)

产量

+-----------------------+--------+---------+------------+----------------+
|       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+ |
+-----------------------+--------+---------+------------+----------------+
Run Code Online (Sandbox Code Playgroud)

输出使用csv2table转换

密码破解程序的CUDA/OpenCL实现可以利用GPU中可用的大量并行性,每秒钟达到数十亿个候选密码.

让我们估计我们可以921600M c/s在非常快的系统上并行完成

T = 966367641600 * 8   
T = 7,730,941,132,800  // bits/sec
Run Code Online (Sandbox Code Playgroud)

运用

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
    );
}
Run Code Online (Sandbox Code Playgroud)

产量

+-----------------------+---------+---------+----------+
|       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+ |
+-----------------------+---------+---------+----------+
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,仍然需要一段时间才能打破一个像样的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;
}
Run Code Online (Sandbox Code Playgroud)

误解

你是对的密码长度很重要,所以密码的熵.大多数建议建议用户在不了解密码强度的情况下使用bcrypt,密码复杂性等

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

在此输入图像描述

来源 | 相关博文

所以我想知道,它的速度肯定很慢,特别是哪种密码强度可以安全使用.

在此输入图像描述 资源

绝对不是6 letters:)

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

结论

这里有一些很好的参考资料,你可能会看到什么

  • 实际上,它取决于成本因素,可以计算BCrypt哈希的速度,这是所有密钥派生函数背后的理念.计算密码的熵并不能说明密码的破解速度有多快.这仅适用于真正随机的密码,由于聪明的[攻击模式](http://hashcat.net/wiki/#attack_modes),其他密码通常会更快地破解. (3认同)
  • 谢谢你的答案.到目前为止,这是最好的一个.我有一个异议 - 我对通行短语有偏见.它们不能仅仅按长度计算,就好像它们是随机密码一样.它们不是随机的.事实上,四个单词短语只有8000 ^ 4,其中8000是从中挑选单词的词汇.它仍然是不错的数字,但不如你的功能重要. (2认同)

Pau*_*mer 0

根据您的最新评论,您希望构建一个主要政府可以接受的密码方案。这些信息很容易获得。