WordPress.org

Make WordPress Core

Opened 6 years ago

Closed 5 years ago

Last modified 5 years ago

#7124 closed enhancement (fixed)

Improve Password Strength Meter

Reported by: Otto42 Owned by:
Milestone: 2.7 Priority: normal
Severity: normal Version:
Component: Optimization Keywords: has-patch needs-testing
Focuses: Cc:

Description

The password strength meter is quite weak in how it determines what a good password is. Basically, it's using a seemingly arbitrary set of rules and scoring mechanisms. While such an approach is simple and easy, it's not particularly sound. It's highly arbitrary, easily bypassed (simple passwords can be marked as strong ones) and some of its rules are seemingly counterproductive.

Note that the current strength meter rates "12Ab!" as a strong password.

To solve this, first, we need to understand what a strength meter really is.

What is "password strength" anyway?

Well, if it's something that we can measure, then the only logical answer is to consider how one cracks a modern password. The answer to this is simple, and has been for quite a while: Brute Force. Since we only store one-way hashes, you have to hash a bunch of passwords from a dictionary or from some other source of passwords, and compare them (or use rainbow tables or something, but salts can prevent that sort of attack).

So, if we're measuring strength in terms of brute force attacks against our password, then we can only really measure it in terms of the amount of time it would take to find the password by random searching. The key here is bit strength.

When you're attacking a modern encryption system, you're doing it with brute force. And the bit strength of that is what determines how long it takes. A 64 bit key is good, a 128 bit key is better, and so on. So we can compare our passwords against each other by considering the number of possible combinations of the passwords and then determining how many of those there are. Easy.

To determine the number of passwords possible given an example password, we can break it down into two characteristics:

  1. Number of total symbols.
  2. Number of symbols used out of sets of symbols.

The first of these is simply the length of the password. Longer passwords are stronger.

The second is a matter of symbol types. Realistically, we have four major groupings:
a) Digits
b) Lowercase alpha characters
c) Uppercase alpha charaters
d) Punctuation symbols (typeable symbols)

Of these, we know how many there are of each: 10, 26, 26, and 31. To figure the equivalent bit strength for a password, we do some simple mathematics.

First, we determine how many of the sets were used in the password. That gives us the total number of possible symbols.
Second, we raise that number to the power of the password length. This gives us the total number of possible passwords.
Finally, we take the binary logarithm of that number of passwords. This tells us how many bits it is in binary, and gives us a small, measurable value for the bit strength of the password. Raising it by 1 bit makes the password twice as hard to crack.

So, some simple Javascript to do this:

function passwordStrength(password) {
	var symbolSize = 0;
	if (password.match(/[0-9]/)) symbolSize +=10;
	if (password.match(/[a-z]/)) symbolSize +=26;
	if (password.match(/[A-Z]/)) symbolSize +=26; 
	if (password.match(/[^a-zA-Z0-9]/)) symbolSize +=31;
	var natLog = Math.log( Math.pow(symbolSize,password.length) );
	var baseTwoLog = natLog / Math.LN2;
	return baseTwoLog;
}

That gives us the bit strength of any given password. A bit strength of 56 or higher would be likely considered "strong". A password of only digits, for example, would need at least 17 of them to reach 56 bit strength. While a password of lowercase letters would need to be at least 12 letters long. Even a password using lower, upper, digits, and symbols would need to be 9 letters long to reach 56 bit strength.

My example from earlier was "12Ab!". In this system, such a password returns a strength of ~32.7. Such a password would not be considered good in this system. The relative values would be as follows:
Bad: Less than 40 bits.
Good: 40 bits.
Strong: 56 bits.
Extra Strong: 64 bits or higher.

Naturally, this is not a complete system of measurement. A dictionary based password can be defeated easily through dictionary attacks, regardless of the strength of it measured in terms of "bits". However, this is still a significant improvement upon what WordPress is currently using.

I've attached a simple patch to the existing javascript to implement this change. Try it. Expand upon it.

Attachments (1)

patch.diff (3.3 KB) - added by Otto42 6 years ago.
Patch for password strength

Download all attachments as: .zip

Change History (9)

Otto426 years ago

Patch for password strength

comment:1 Otto426 years ago

  • Keywords has-patch 2nd-opinion added

comment:2 Otto426 years ago

  • Keywords 2nd-opinion removed
  • Milestone changed from 2.9 to 2.7

Would really like to see this get pushed in, if at all possible.

comment:3 jacobsantos5 years ago

As would I. Seems to simplify the code quite a bit.

comment:4 jacobsantos5 years ago

  • Keywords needs-testing added

comment:5 ryan5 years ago

We need to retain the password == username check. Are there any brute-force tools that check for repetition? If so we might want to retain that too.

comment:6 follow-up: ryan5 years ago

Heh, I can't tell red from white. The username check is there. Nevermind.

comment:7 ryan5 years ago

  • Resolution set to fixed
  • Status changed from new to closed

(In [9276]) Improved password strength meter from Otto42. fixes #7124

comment:8 in reply to: ↑ 6 Viper007Bond5 years ago

Replying to ryan:

Heh, I can't tell red from white. The username check is there. Nevermind.

No worries, I read it the same way. Was thinking the whole checker was replaced by the green bit.

Note: See TracTickets for help on using tickets.