Alternatively, the HaveIBeenPwned API takes an interesting approach to check passwords without sending the password to the server:
- Take a SHA1 hash of the password.
- Truncate it to five characters.
- Send this to the server.
- The server returns the full SHA1 hashes of all known (insecure) passwords with these five characters at the start of their hash.
- The client checks whether the password hash is in this list.
This way, you don't submit the whole password but the client also doesn't need to retrieve the whole password database.
My go-to for passphrase strength questions is NIST SP 800-63b: "Digital Identity Guidelines: Authentication and Lifecycle Management". While this is a US Gov standard, it also serves as sound guidance for the rest of us.
18.104.22.168 Memorized Secret Verifiers
When processing requests to establish and change memorized secrets, verifiers SHALL compare the prospective secrets against a list that contains values known to be commonly-used, expected, or compromised. For example, the list MAY include, but is not limited to:
Passwords obtained from previous breach corpuses.
Repetitive or sequential characters (e.g. ‘aaaaaa’, ‘1234abcd’).
Context-specific words, such as the name of the service, the username, and derivatives thereof.
If the chosen secret is found in the list, the CSP or verifier SHALL advise the subscriber that they need to select a different secret, SHALL provide the reason for rejection, and SHALL require the subscriber to choose a different value.
Verifiers SHOULD offer guidance to the subscriber, such as a password-strength meter[Meters], to assist the user in choosing a strong memorized secret. This is particularly important following the rejection of a memorized secret on the above list as it discourages trivial modification of listed (and likely very weak) memorized secrets[Blacklists].
Notice how they suggest using strength meters (like zxcvbn) simply as a UI aid, but the actual enforcement is done against a blacklist.
Measuring password entropy is not an easy task, and basically not even feasible to do. Any system or measurement can be circumvented if tried hard enough. If users really wanted, they could probably even get away with using something like
It's much better to give user guidelines on how to pick a good password, such as:
It is recommended to use a password manager to generate a long, random password and store it in a safe place.
If using a password manager is not possible, it's encouraged to use Diceware to generate a sufficiently good password.
... And so on and so forth ...
"password strength" is not a clearly defined metric. And when implementing such a checker, please do keep in mind that most libraries still implement the outdated and wrong old NIST guidelines (special characters, numbers, that nonsense).
The strongest indicator of password strength is length. Requiring a reasonably high minimum length, which (2019) is around 12 characters or 16 for important things, is the strongest single check you can have. Mike already included the relevant NIST recommendations for more details.
If you use a library, choose one that implements the current NIST guidelines, not the old ones.