Last active
August 29, 2015 14:05
-
-
Save justenwalker/f2c1d8f10a7538b4d671 to your computer and use it in GitHub Desktop.
Password Checker
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
###* | |
* @namespace PasswordChecker | |
* | |
* Utility class to check a password's complexity | |
* | |
* | |
* {@link PasswordChecker.strength} returns an object containing: | |
* | |
* - *summary* The results of {@link PasswordChecker.summary} | |
* - *total* The total raw score for the password | |
* - *strength* The strength of the password scaled to the min/max values of score. | |
* It is a value between 0 and 100, so it can be used as the 'strength' on a meter | |
* | |
* {@link PasswordChecker.summary} returns an object containing: | |
* | |
* - *length* The length of the password | |
* - *characters* The number of unique characters in the password | |
* - *transitions* The number of transitions between character types | |
* - *types* The number of different character types | |
### | |
class PasswordChecker | |
###* | |
* Gets the character's type | |
* @param {string} char Single character to test | |
* @return {Number} Type of character. 1 = Upper Case, 2 = Lower Case, 3 = Numbers, 4 = ASCII Symbols, 5 = Other | |
### | |
@charType: (char) -> | |
code = char.charCodeAt(0) | |
switch | |
## Upper Case | |
when code >= 65 && code <= 90 then 1 | |
## Lower Case | |
when code >= 97 && code <= 122 then 2 | |
## Numbers | |
when code >= 48 && code <= 57 then 3 | |
## ASCII Symbols | |
when code < 128 then 4 | |
## Everything Else | |
else 5 | |
###* | |
* Get a summary of the password's characteristics | |
* @param {String} password Password to check | |
* @return {Object} contains length, characters, transitions, and types | |
* @static | |
### | |
@summary: (password) -> | |
count = password.length | |
transitions = 0 | |
uniques = 0 | |
types = 0 | |
# State | |
lastType = 0 | |
uniqueChars = "" | |
uniqueTypes = [] | |
for i in [0..count-1] | |
c = password.charAt(i) | |
thisType = @charType(c) | |
if thisType not in uniqueTypes | |
types++ | |
uniqueTypes.push thisType | |
if thisType != lastType | |
transitions++ | |
lastType = thisType | |
if uniqueChars.indexOf(c) < 0 | |
uniques++ | |
uniqueChars += c | |
# First transition doesn't count | |
{length: count, characters: uniques, transitions: transitions - 1, types: types} | |
###* | |
* Measure the strength of the password | |
* @param {String} password Password to check | |
* @param {Number} min Minimum score (This score and below has strength of 0) | |
* @param {Number} max Maximum score (This score and above has strength of 100) | |
* @returns {Object} contains summary, strength, and raw total score | |
* @static | |
### | |
@strength: (password, min, max) -> | |
summary = @summary(password) | |
{length, characters, transitions, types} = summary | |
total = length + characters + (2 * transitions) + ( 2 * types ) | |
summary['length_pct'] = 1.0 * length / total | |
summary['characters_pct'] = 1.0 * characters / total | |
summary['transitions_pct'] = 2.0 * transitions / total | |
summary['types_pct'] = 2.0 * types / total | |
strength = Math.round(Math.min( Math.max(total - min,0) / (max - min) , 1.0 ) * 100.0) | |
{ summary: summary , strength: strength, total: total } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A good MIN appears to be 20 points. Anything below this is probably useless as a password.
70 or 80 appears to be a decent MAX value.
Here are a few test vectors for some passwords of varying strength: https://jsfiddle.net/uh9duyhn/1/