@regru/jquery-complexify
Version:
Complexify helps you to accurately gauge the quality of a user's password to give them visual feedback, and to enforce a minimum level of security.
195 lines (174 loc) • 7.09 kB
JavaScript
/*
http://github.com/danpalmer/jquery.complexify.js
This code is distributed under the WTFPL v2:
*/
(function ($) {
$.fn.extend({
complexify: function(options, callback) {
var MIN_COMPLEXITY = 49; // 12 chars with Upper, Lower and Number
var MAX_COMPLEXITY = 120; // 25 chars, all charsets
var CHARSETS = [
// Commonly Used
////////////////////
[], // Space
[], // Numbers
[], // Uppercase
[], // Lowercase
[], // Punctuation
[], // Punctuation
[], // Punctuation
[], // Punctuation
// Everything Else
////////////////////
[], // Latin-1 Supplement
[], // Latin Extended-A
[], // Latin Extended-B
[], // IPA Extensions
[], // Spacing Modifier Letters
[], // Combining Diacritical Marks
[], // Greek
[], // Cyrillic
[], // Armenian
[], // Hebrew
[], // Arabic
[], // Syriac
[], // Thaana
[], // Devanagari
[], // Bengali
[], // Gurmukhi
[], // Gujarati
[], // Oriya
[], // Tamil
[], // Telugu
[], // Kannada
[], // Malayalam
[], // Sinhala
[], // Thai
[], // Lao
[], // Tibetan
[], // Myanmar
[], // Georgian
[], // Hangul Jamo
[], // Ethiopic
[], // Cherokee
[], // Unified Canadian Aboriginal Syllabics
[], // Ogham
[], // Runic
[], // Khmer
[], // Mongolian
[], // Latin Extended Additional
[], // Greek Extended
[], // General Punctuation
[], // Superscripts and Subscripts
[], // Currency Symbols
[], // Combining Marks for Symbols
[], // Letterlike Symbols
[], // Number Forms
[], // Arrows
[], // Mathematical Operators
[], // Miscellaneous Technical
[], // Control Pictures
[], // Optical Character Recognition
[], // Enclosed Alphanumerics
[], // Box Drawing
[], // Block Elements
[], // Geometric Shapes
[], // Miscellaneous Symbols
[], // Dingbats
[], // Braille Patterns
[], // CJK Radicals Supplement
[], // Kangxi Radicals
[], // Ideographic Description Characters
[], // CJK Symbols and Punctuation
[], // Hiragana
[], // Katakana
[], // Bopomofo
[], // Hangul Compatibility Jamo
[], // Kanbun
[], // Bopomofo Extended
[], // Enclosed CJK Letters and Months
[], // CJK Compatibility
[], // CJK Unified Ideographs Extension A
[], // CJK Unified Ideographs
[], // Yi Syllables
[], // Yi Radicals
[], // Hangul Syllables
[], // High Surrogates
[], // High Private Use Surrogates
[], // Low Surrogates
[], // Private Use
[], // CJK Compatibility Ideographs
[], // Alphabetic Presentation Forms
[], // Arabic Presentation Forms-A
[], // Combining Half Marks
[], // CJK Compatibility Forms
[], // Small Form Variants
[], // Arabic Presentation Forms-B
[], // Specials
[], // Halfwidth and Fullwidth Forms
[] // Specials
];
var defaults = {
minComplexity: MIN_COMPLEXITY,
maxComplexity: MAX_COMPLEXITY,
minimumChars: 8,
strengthScaleFactor: 1,
bannedPasswords: window.COMPLEXIFY_BANLIST || [],
banMode: 'strict' // (strict|loose)
};
if($.isFunction(options) && !callback) {
callback = options;
options = {};
}
options = $.extend(defaults, options);
function additionalComplexityForCharset(str, charset) {
for (var i = str.length - 1; i >= 0; i--) {
if (charset[0] <= str.charCodeAt(i) && str.charCodeAt(i) <= charset[1]) {
return charset[1] - charset[0] + 1;
}
}
return 0;
}
function inBanlist(str) {
if (options.banMode === 'strict') {
for (var i = 0; i < options.bannedPasswords.length; i++) {
if (str.toLowerCase().indexOf(options.bannedPasswords[i].toLowerCase()) !== -1) {
return true;
}
}
return false;
} else {
return $.inArray(str, options.bannedPasswords) > -1 ? true : false;
}
}
function evaluateSecurity() {
var password = $(this).val();
var complexity = 0, valid = false;
// Reset complexity to 0 when banned password is found
if (!inBanlist(password)) {
// Add character complexity
for (var i = CHARSETS.length - 1; i >= 0; i--) {
complexity += additionalComplexityForCharset(password, CHARSETS[i]);
}
} else {
complexity = 1;
}
// Use natural log to produce linear scale
complexity = Math.log(Math.pow(complexity, password.length)) * (1/options.strengthScaleFactor);
// Scale to percentage, so it can be used for a progress bar
complexity = (complexity / options.maxComplexity) * 100;
complexity = (complexity > 100) ? 100 : complexity;
valid = (complexity > options.minComplexity && password.length >= options.minimumChars);
callback.call(this, valid, complexity);
}
this.each(function () {
if($(this).val()) {
evaluateSecurity.apply(this);
}
});
return this.each(function () {
$(this).bind('keyup focus input propertychange mouseup', evaluateSecurity);
});
}
});
})(jQuery);