What is the strength of a password that is considered sufficient for use with the password_hash function?

As I understand it, one of the most important features of the new PHP hashing of add-ons (or bcrypt in general) is the speed of the algorithm, which significantly slows down the brute force attack method.

But still it works at some speed, certainly enough to attack the dictionary and to sort through weak passwords, presumably shorter than six alphanumeric characters.

So, I want to know how slow it is, of course, and, in particular, what password strength is considered safe to use. β€œAs strong as you can imagine,” is not the answer, because the strength of a password is always a compromise between security and usability. Therefore, I am looking for the minimum strength that can be considered safe and even future.

Please note that I am a practitioner - therefore, a specific answer based on specific numbers is preferable to long and windy theoretical considerations with an uncertain conclusion.

To clarify a little more, the worst case scenario is supposedly: the user database is stolen and someone tries to decrypt the passwords. Rainbow tables are not an option due to strong salt. Thus, the only vectors left in the dictionary are dictionary attack and brute force. Assuming we supply users with pre-generated passwords, excluding dictionary attack. That's why password strength is my only problem.

Update:
It seems they misunderstood me. The question, for me, is quite practical , and quite responsible . And of great importance .

Without determining the sufficient strength of the password, the use of this new algorithm can be called into question. Why worry about a good algorithm if passwords are still insecure? So, I am firmly convinced that along with the recommendation to use the new hashing algorithm, there should always be a recommendation about the minimum password strength. What I want to know.

In other words, if there is a certain certainty about one part - the algorithm ("use this, not the other!"), Then, apparently, there should be certainty about the other part - the strength of the password, with which you can speak with the same level of authority, Otherwise, the weakest part will spoil the strongest.
+7
security php bcrypt hash php-password-hash
source share
3 answers

I'm not sure I understand your question clearly, but I would just focus on the strength of the password and how it affects brute force attack.

But still it works at some speed, certainly enough to attack the dictionary and to sort through weak passwords, presumably shorter than six alphanumeric characters.

Introduction

For a moment, forget about the hash algorithm (md5, sha, pbkdf2 bcrypt, scrypt, etc.) and do not focus on Strength Password

Wiki Password Strength

This is an indicator of the effectiveness of the password in resisting guessing and brute force attacks. In his usual form, he calculates how many trials an attacker who does not have direct access to a password, on average, had to guess it correctly.

It can simply be calculated as:

enter image description here

Entropy is given by the symbol H=Llog2N , where L is the length of the password, and N is the size of the alphabet and is usually measured in bits.

Hash function

password_hash uses [bcrypt][4] by default, for which a password is enough, but there are better alternatives like PBKDF2 or scrypt for more information on what I mean, see How to keep a password safe

Using oclHashcat , let's evaluate the following

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

Please note that this is an estimate and may vary depending on the hardware capacity.

With the help of this information we can safely calculate how long it will take to iterate over with another password.

Calculate Entropy in 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 ); } 

Exit

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

Result converted using csv2table

CUDA / OpenCL password cracking capabilities can use the huge amount of parallelism available in GPUs, reaching billions of potential passwords per second .

Lets evaluate that we can do 921600M c/s in parallel on a very fast system

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

Using

 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 ); } 

Exit

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

As you can see, it still takes some time to break a decent 12 digits.

Function used

 // 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) (eg PIN) "/[0-9]+/" => 10, // Arabic numerals (0–9) (eg PIN) "/[az]+/" => 26, // Case insensitive Latin alphabet (az) "/[AZ]+/" => 26, // Case insensitive Latin alphabet (AZ) '/[\!\@#$%\?\&\*\(\)_\-\+=~:;.]+/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, AF) (eg WEP keys) if (ctype_xdigit($password)){ $N = 16; } // Fix pure number cases that might have been changed by hexadecimal // Arabic numerals (0–9) (eg 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; } 

Misunderstanding

You are right, the length of the password is important, since the entropy of the password. Most recommendations advise users to use bcrypt , password complexity, etc. Without understanding password strength

But the fact that the simplest passwords can often be the strongest.

enter image description here

Source | Linked Blog Post

So, I want to know how slow it is, of course, and, in particular, what password strength is considered safe to use.

enter image description here A source

Definitely not 6 letters :)

  • <28 bits = very weak; may contain family members.
  • 28 - 35 bits = weak; Most people, often good at passwords for logging into a desktop computer, should be avoided.
  • 36 - 59 bits = Reasonable; fairly secure passwords for network and corporate passwords.
  • 60 - 127 bit = Strong; may be useful to protect financial information.
  • 128+ bits = Very Strong; often overkill

Conclusion

Here are some good links you can look at

+31
source share

This is an interesting question, although hardly anyone can give a definitive answer.

As you know, BCrypt (and other key generation functions) have a cost factor. Usually you configure this cost factor until your server takes some time to hash the password, for example 1 millisecond. Thus, an attacker with the same hardware can calculate 1,000 hashes / s.

If you compare the oclHashcat (GPU) speed with its processor version, you see a coefficient of 100 for MD5, so we can guess that an attacker can impose about 1,000,000 hashes / s (BCrypt is not compatible with the GPU, but it should be safe). This is a path from 8'000'000'000 MD5 hashes / s and depends on the cost factor.

The second problem is the strength of the password. If it is part of a general dictionary, it can be found quickly, even if it is long, so the minimum length does not guarantee a strong password. If this is β€œrandom” enough, the only way to crack it is to force it (the best case for us). For this case, we can try the math:

 Password alphabet: 62 characters (az AZ 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 

Of course, this is based on many assumptions, perhaps the attacker may work faster, or the password is not so strong. I myself require a minimum of 8 characters, but I recommend using a passphrase.

EDIT: Another note about password strength:

The strength of a password cannot be realistically calculated, of course, not by a formula. Every serious password cracking tool will support hybrid attacks and attack- based rules . Passwords that look strong can be very weak if they are part of a dictionary or managed by the rule, so it depends on the imagination of the attacker how quickly the password can be cracked.

The only thing we can say is that long and random passwords are strong, because there is no simpler way to crack them than force enforcement. But it doesn’t help here, because users will choose their passwords, not the developer who created the website, and they don’t choose the perfect passwords.

+3
source share

In your last comment, you want to create a password scheme that would be acceptable to large governments. This information is easily accessible.

0
source share

All Articles