From 2fff2d096835f862e50064bef4d6bd5a3049d29d Mon Sep 17 00:00:00 2001 From: Max Semenik Date: Thu, 5 Aug 2010 19:18:20 +0000 Subject: [PATCH] Follow-up to r70520: forgot to add new files --- skins/common/password.css | 17 +++++ skins/common/password.js | 136 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 skins/common/password.css create mode 100644 skins/common/password.js diff --git a/skins/common/password.css b/skins/common/password.css new file mode 100644 index 0000000000..7983e91d90 --- /dev/null +++ b/skins/common/password.css @@ -0,0 +1,17 @@ +span.mw-password-bad { + background: red; + color: yellow; + font-weight: bold; +} + +.mw-password-mediocre { + background: yellow; +} + +.mw-password-acceptable { + background: silver; +} + +.mw-password-good { + background: green; +} \ No newline at end of file diff --git a/skins/common/password.js b/skins/common/password.js new file mode 100644 index 0000000000..990b270273 --- /dev/null +++ b/skins/common/password.js @@ -0,0 +1,136 @@ +/** + * Password strength checker + * @license WTFPL 2.0 + * All scores are ranged approximately 0 (total disaster) - 100 (_looks_ great) + * @todo Check for popular passwords and keyboard sequences (QWERTY, etc) + */ + +function bruteForceComplexity( pwd ) { + var score = 0; + + if ( pwd.length < 16 ) { + score = pwd.length * 5; + } else { + score = 80; + } + + var regexes = [ + /[a-z]/, + /[A-Z]/, + /[0-9]/, + /[-_;:\.,'"`~!@#$%\^&\*\(\)\[\]\{\} ]/ ]; + + var charClasses = 0; + for ( var i in regexes ) { + if ( pwd.match( regexes[i] ) ) { + charClasses++; + } + } + + var matches = pwd.match( /[\x80-\uFFFF]/g ); + if ( matches ) { + charClasses++; + + // poor man's isUpper() and isLower() + var i, lower = false, upper = false; + for ( i in matches ) { + var ch = matches[i]; + upper |= ch != ch.toLowerCase(); + lower |= ch != ch.toUpperCase(); + if ( upper && lower ) break; + } + if ( upper && lower ) { + charClasses++; + } + } + score += ( charClasses - 1 ) * 10; + + return score; +} + +function repetitionScore( pwd ) { + var unique = ''; + for ( var i in pwd ) { + if ( unique.indexOf( pwd[i] ) < 0 ) { + unique += pwd[i]; + } + } + var ratio = pwd.length / unique.length - 0.4; // allow up to 40% repetition, reward for less, penalize for more + + return 100 / ratio; +} + +function sequenceScore( pwd ) { + pwd = pwd.concat( '\0' ); + var score = 100, sequence = 1; + for ( var i = 1; i < pwd.length; i++ ) { + if ( pwd.charCodeAt( i ) == pwd.charCodeAt(i - 1) + 1 ) { + sequence++; + } else { + if ( sequence > 2 ) { + score -= Math.sqrt( sequence ) * 15; + } + sequence = 1; + } + } + for ( var i = 1; i < pwd.length; i++ ) { + if ( pwd.charCodeAt( i ) == pwd.charCodeAt(i - 1) - 1 ) { + sequence++; + } else { + if ( sequence > 2 ) { + score -= Math.sqrt( sequence ) * 15; + } + sequence = 1; + } + } + return score; +} + +(function( $ ) { + function passwordChanged() { + retypeChanged(); + var pwd = $( passwordSecurity.password ).val(); + if ( pwd == '' ) { + $( '#password-strength' ).html( '' ); + return; + } + if ( pwd.length > 100 ) pwd = pwd.slice( 0, 100 ); + var score = Math.min( + bruteForceComplexity( pwd ), + repetitionScore( pwd ), + sequenceScore( pwd ) + ); + var result = 'good'; + if ( score < 40 ) { + result = 'bad'; + } else if ( score < 60 ) { + result = 'mediocre'; + } else if ( score < 85 ) { + result = 'acceptable'; + } + var message = '' + passwordSecurity.messages['password-strength-' + result] + + ''; + $( '#password-strength' ).html( + passwordSecurity.messages['password-strength'].replace( '$1', message ) + ); + } + + function retypeChanged() { + var pwd = $( passwordSecurity.password ).val(); + var retype = $( passwordSecurity.retype ).val(); + var message; + if ( pwd == '' || pwd == retype ) { + message = ''; + } else if ( retype == '' ) { + message = passwordSecurity.messages['password-retype']; + } else { + message = passwordSecurity.messages['password-retype-mismatch']; + } + $( '#password-retype' ).html( message ); + } + + $( document ).ready( function() { + $( passwordSecurity.password ).bind( 'keyup change', passwordChanged ); + $( passwordSecurity.retype ).bind( 'keyup change', retypeChanged ); + }) +})(jQuery); -- 2.20.1