password_strength 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: eb271520f8e1e9f75c210e2619ce81c63982b014
4
+ data.tar.gz: a7b360fded5d8808dc8eb7f910375b01e952cda5
5
+ SHA512:
6
+ metadata.gz: 6973d5426f558cdb89a9e57e2cee7579a3b1413d3a3f1f8b874ba25ec1fd5934c7dd9ccc3fb9806129850f521402e3f2cdf12d6bcbdd55f441abeacc6b3160a0
7
+ data.tar.gz: 8683f5d04cc022c6f0c1b49345ebc626d130a88ce6d83385abaf75ace78b8b41fcb7a3c90ce650d09afa8ecd77e8ffb9536c223ba6c066a7f13ea85ff9e2fd24
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ pkg
2
+ coverage
3
+ doc
4
+ /gemfiles/*.lock
data/.travis.yml ADDED
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ script: "bundle exec rake test"
3
+
4
+ rvm:
5
+ - 2.1.1
6
+ - 2.0.0
7
+
8
+ gemfile:
9
+ - gemfiles/ar_3_2.gemfile
10
+ - gemfiles/ar_4_0.gemfile
11
+ - gemfiles/ar_4_1.gemfile
12
+
13
+ notifications:
14
+ email:
15
+ - fnando.vieira@gmail.com
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "http://rubygems.org"
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,82 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ password_strength (0.4.0)
5
+ activerecord
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ activemodel (4.0.4)
11
+ activesupport (= 4.0.4)
12
+ builder (~> 3.1.0)
13
+ activerecord (4.0.4)
14
+ activemodel (= 4.0.4)
15
+ activerecord-deprecated_finders (~> 1.0.2)
16
+ activesupport (= 4.0.4)
17
+ arel (~> 4.0.0)
18
+ activerecord-deprecated_finders (1.0.3)
19
+ activesupport (4.0.4)
20
+ i18n (~> 0.6, >= 0.6.9)
21
+ minitest (~> 4.2)
22
+ multi_json (~> 1.3)
23
+ thread_safe (~> 0.1)
24
+ tzinfo (~> 0.3.37)
25
+ arel (4.0.2)
26
+ atomic (1.1.16)
27
+ awesome_print (1.2.0)
28
+ builder (3.1.4)
29
+ coderay (1.1.0)
30
+ columnize (0.3.6)
31
+ debugger (1.6.6)
32
+ columnize (>= 0.3.1)
33
+ debugger-linecache (~> 1.2.0)
34
+ debugger-ruby_core_source (~> 1.3.2)
35
+ debugger-linecache (1.2.0)
36
+ debugger-ruby_core_source (1.3.2)
37
+ diff-lcs (1.2.5)
38
+ i18n (0.6.9)
39
+ method_source (0.8.2)
40
+ minitest (4.7.5)
41
+ multi_json (1.9.2)
42
+ pry (0.9.12.6)
43
+ coderay (~> 1.0)
44
+ method_source (~> 0.8)
45
+ slop (~> 3.4)
46
+ pry-debugger (0.2.2)
47
+ debugger (~> 1.3)
48
+ pry (~> 0.9.10)
49
+ pry-meta (0.0.6)
50
+ awesome_print
51
+ pry
52
+ pry-debugger
53
+ pry-remote
54
+ pry-remote (0.1.8)
55
+ pry (~> 0.9)
56
+ slop (~> 3.0)
57
+ rake (10.2.2)
58
+ rspec (2.14.1)
59
+ rspec-core (~> 2.14.0)
60
+ rspec-expectations (~> 2.14.0)
61
+ rspec-mocks (~> 2.14.0)
62
+ rspec-core (2.14.8)
63
+ rspec-expectations (2.14.5)
64
+ diff-lcs (>= 1.1.3, < 2.0)
65
+ rspec-mocks (2.14.6)
66
+ slop (3.5.0)
67
+ sqlite3 (1.3.9)
68
+ test-unit (2.5.5)
69
+ thread_safe (0.3.1)
70
+ atomic (>= 1.1.7, < 2)
71
+ tzinfo (0.3.39)
72
+
73
+ PLATFORMS
74
+ ruby
75
+
76
+ DEPENDENCIES
77
+ password_strength!
78
+ pry-meta
79
+ rake
80
+ rspec
81
+ sqlite3
82
+ test-unit
data/README.rdoc CHANGED
@@ -1,5 +1,7 @@
1
1
  = Introduction
2
2
 
3
+ {<img src="https://travis-ci.org/fnando/password_strength.svg" alt="Build Status" />}[https://travis-ci.org/fnando/password_strength]
4
+
3
5
  Validates the strength of a password according to several rules:
4
6
 
5
7
  * size
@@ -10,6 +12,7 @@ Validates the strength of a password according to several rules:
10
12
  * password contains username
11
13
  * sequences (123, abc, aaa)
12
14
  * repetitions
15
+ * can't be a common password (view list at support/common.txt)
13
16
 
14
17
  Some results:
15
18
 
@@ -21,7 +24,11 @@ Some results:
21
24
 
22
25
  = Install
23
26
 
24
- sudo gem install password_strength
27
+ gem install password_strength
28
+
29
+ or put this in your Gemfile:
30
+
31
+ gem "password_strength"
25
32
 
26
33
  If you want the source go to http://github.com/fnando/password_strength
27
34
 
@@ -50,7 +57,7 @@ If you want the source go to http://github.com/fnando/password_strength
50
57
 
51
58
  = ActiveRecord
52
59
 
53
- The PasswordStrength library comes with ActiveRecord support (tested on AR 2.3.5 and 3.0.0-beta).
60
+ The PasswordStrength library comes with ActiveRecord support.
54
61
 
55
62
  class Person < ActiveRecord::Base
56
63
  validates_strength_of :password
@@ -130,18 +137,22 @@ If you just want to overwrite the callback, you can simple do
130
137
 
131
138
  Get the files:
132
139
 
133
- * http://github.com/fnando/password_strength/raw/master/javascripts/password_strength.js
134
- * http://github.com/fnando/password_strength/raw/master/javascripts/jquery.strength.js
140
+ * http://github.com/fnando/password_strength/raw/master/app/assets/javascripts/password_strength.js
141
+ * http://github.com/fnando/password_strength/raw/master/app/assets/javascripts/jquery.strength.js
135
142
 
136
- = TO-DO
143
+ If you're using asset pipeline, just add the following lines to your `application.js`.
137
144
 
138
- * Rake task to get the latest JavaScript file
145
+ ```javascript
146
+ //= require jquery
147
+ //= require password_strength
148
+ //= require jquery_strength
149
+ ```
139
150
 
140
151
  = License
141
152
 
142
153
  (The MIT License)
143
154
 
144
- Copyright © 2010:
155
+ Copyright © 2010-2014:
145
156
 
146
157
  * Nando Vieira (http://simplesideias.com.br)
147
158
 
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require "bundler"
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require "rake/testtask"
5
+ require "rdoc/task"
6
+
7
+ Rake::TestTask.new do |t|
8
+ t.libs += %w[test lib]
9
+ t.ruby_opts = %w[-rubygems]
10
+ t.test_files = FileList["test/**/*_test.rb"]
11
+ t.verbose = true
12
+ end
13
+
14
+ Rake::RDocTask.new do |rdoc|
15
+ rdoc.main = "README.rdoc"
16
+ rdoc.rdoc_dir = "doc"
17
+ rdoc.title = "Password Strength"
18
+ rdoc.options += %w[ --line-numbers --inline-source --charset utf-8 ]
19
+ rdoc.rdoc_files.include("README.rdoc", "CHANGELOG.rdoc")
20
+ rdoc.rdoc_files.include("lib/**/*.rb")
21
+ end
@@ -0,0 +1,62 @@
1
+ (function($){
2
+ $.strength = function(username, password, options, callback) {
3
+ if (typeof(options) == "function") {
4
+ callback = options;
5
+ options = {};
6
+ } else if (!options) {
7
+ options = {};
8
+ }
9
+
10
+ var usernameField = $(username);
11
+ var passwordField = $(password);
12
+ var strength = new PasswordStrength();
13
+
14
+ strength.exclude = options["exclude"];
15
+
16
+ callback = callback || $.strength.callback;
17
+
18
+ var handler = function(){
19
+ strength.username = $(usernameField).val();
20
+
21
+ if ($(usernameField).length == 0) {
22
+ strength.username = username;
23
+ }
24
+
25
+ strength.password = $(passwordField).val();
26
+
27
+ if ($(passwordField).length == 0) {
28
+ strength.password = password;
29
+ }
30
+
31
+ strength.test();
32
+ callback(usernameField, passwordField, strength);
33
+ };
34
+
35
+ $(usernameField).keydown(handler);
36
+ $(usernameField).keyup(handler);
37
+
38
+ $(passwordField).keydown(handler);
39
+ $(passwordField).keyup(handler);
40
+ };
41
+
42
+ $.extend($.strength, {
43
+ callback: function(username, password, strength){
44
+ var img = $(password).next("img.strength");
45
+
46
+ if (!img.length) {
47
+ $(password).after("<img class='strength'>");
48
+ img = $("img.strength");
49
+ }
50
+
51
+ $(img)
52
+ .removeClass("weak")
53
+ .removeClass("good")
54
+ .removeClass("strong")
55
+ .addClass(strength.status)
56
+ .attr("src", $.strength[strength.status + "Image"]);
57
+ },
58
+ weakImage: "/images/weak.png",
59
+ goodImage: "/images/good.png",
60
+ strongImage: "/images/strong.png"
61
+ });
62
+ })(jQuery);
@@ -0,0 +1,270 @@
1
+ var PasswordStrength = (function(){
2
+ var MULTIPLE_NUMBERS_RE = /\d.*?\d.*?\d/;
3
+ var MULTIPLE_SYMBOLS_RE = /[!@#$%^&*?_~].*?[!@#$%^&*?_~]/;
4
+ var UPPERCASE_LOWERCASE_RE = /([a-z].*[A-Z])|([A-Z].*[a-z])/;
5
+ var SYMBOL_RE = /[!@#\$%^&*?_~]/;
6
+
7
+ function PasswordStrength() {
8
+ this.username = null;
9
+ this.password = null;
10
+ this.score = 0;
11
+ this.status = null;
12
+ }
13
+
14
+ PasswordStrength.fn = PasswordStrength.prototype;
15
+
16
+ PasswordStrength.fn.test = function() {
17
+ var score;
18
+ this.score = score = 0;
19
+
20
+ if (this.containInvalidMatches()) {
21
+ this.status = "invalid";
22
+ } else if (this.usesCommonWord()) {
23
+ this.status = "invalid";
24
+ } else {
25
+ score += this.scoreFor("password_size");
26
+ score += this.scoreFor("numbers");
27
+ score += this.scoreFor("symbols");
28
+ score += this.scoreFor("uppercase_lowercase");
29
+ score += this.scoreFor("numbers_chars");
30
+ score += this.scoreFor("numbers_symbols");
31
+ score += this.scoreFor("symbols_chars");
32
+ score += this.scoreFor("only_chars");
33
+ score += this.scoreFor("only_numbers");
34
+ score += this.scoreFor("username");
35
+ score += this.scoreFor("sequences");
36
+ score += this.scoreFor("repetitions");
37
+
38
+ if (score < 0) {
39
+ score = 0;
40
+ }
41
+
42
+ if (score > 100) {
43
+ score = 100;
44
+ }
45
+
46
+ if (score < 35) {
47
+ this.status = "weak";
48
+ }
49
+
50
+ if (score >= 35 && score < 70) {
51
+ this.status = "good";
52
+ }
53
+
54
+ if (score >= 70) {
55
+ this.status = "strong";
56
+ }
57
+ }
58
+
59
+ this.score = score;
60
+ return this.score;
61
+ };
62
+
63
+ PasswordStrength.fn.scoreFor = function(name) {
64
+ score = 0;
65
+
66
+ switch (name) {
67
+ case "password_size":
68
+ if (this.password.length < 4) {
69
+ score = -100;
70
+ } else {
71
+ score = this.password.length * 4;
72
+ }
73
+ break;
74
+
75
+ case "numbers":
76
+ if (this.password.match(MULTIPLE_NUMBERS_RE)) {
77
+ score = 5;
78
+ }
79
+ break;
80
+
81
+ case "symbols":
82
+ if (this.password.match(MULTIPLE_SYMBOLS_RE)) {
83
+ score = 5;
84
+ }
85
+ break;
86
+
87
+ case "uppercase_lowercase":
88
+ if (this.password.match(UPPERCASE_LOWERCASE_RE)) {
89
+ score = 10;
90
+ }
91
+ break;
92
+
93
+ case "numbers_chars":
94
+ if (this.password.match(/[a-z]/i) && this.password.match(/[0-9]/)) {
95
+ score = 15;
96
+ }
97
+ break;
98
+
99
+ case "numbers_symbols":
100
+ if (this.password.match(/[0-9]/) && this.password.match(SYMBOL_RE)) {
101
+ score = 15;
102
+ }
103
+ break;
104
+
105
+ case "symbols_chars":
106
+ if (this.password.match(/[a-z]/i) && this.password.match(SYMBOL_RE)) {
107
+ score = 15;
108
+ }
109
+ break;
110
+
111
+ case "only_chars":
112
+ if (this.password.match(/^[a-z]+$/i)) {
113
+ score = -15;
114
+ }
115
+ break;
116
+
117
+ case "only_numbers":
118
+ if (this.password.match(/^\d+$/i)) {
119
+ score = -15;
120
+ }
121
+ break;
122
+
123
+ case "username":
124
+ if (this.password == this.username) {
125
+ score = -100;
126
+ } else if (this.password.indexOf(this.username) != -1) {
127
+ score = -15;
128
+ }
129
+ break;
130
+
131
+ case "sequences":
132
+ score += -15 * this.sequences(this.password);
133
+ score += -15 * this.sequences(this.reversed(this.password));
134
+ break;
135
+
136
+ case "repetitions":
137
+ score += -(this.repetitions(this.password, 2) * 4);
138
+ score += -(this.repetitions(this.password, 3) * 3);
139
+ score += -(this.repetitions(this.password, 4) * 2);
140
+ break;
141
+ };
142
+
143
+ return score;
144
+ };
145
+
146
+ PasswordStrength.fn.isGood = function() {
147
+ return this.status == "good";
148
+ };
149
+
150
+ PasswordStrength.fn.isWeak = function() {
151
+ return this.status == "weak";
152
+ };
153
+
154
+ PasswordStrength.fn.isStrong = function() {
155
+ return this.status == "strong";
156
+ };
157
+
158
+ PasswordStrength.fn.isInvalid = function() {
159
+ return this.status == "invalid";
160
+ };
161
+
162
+ PasswordStrength.fn.isValid = function(level) {
163
+ if(level == "strong") {
164
+ return this.isStrong();
165
+ } else if (level == "good") {
166
+ return this.isStrong() || this.isGood();
167
+ } else {
168
+ return !this.containInvalidMatches();
169
+ }
170
+ };
171
+
172
+ PasswordStrength.fn.containInvalidMatches = function() {
173
+ if (!this.exclude) {
174
+ return false;
175
+ }
176
+
177
+ if (!this.exclude.test) {
178
+ return false;
179
+ }
180
+
181
+ return this.exclude.test(this.password.toString());
182
+ };
183
+
184
+ PasswordStrength.fn.usesCommonWord = function() {
185
+ return PasswordStrength.commonWords.indexOf(this.password.toLowerCase()) >= 0;
186
+ };
187
+
188
+ PasswordStrength.fn.sequences = function(text) {
189
+ var matches = 0;
190
+ var sequenceSize = 0;
191
+ var codes = [];
192
+ var len = text.length;
193
+ var previousCode, currentCode;
194
+
195
+ for (var i = 0; i < len; i++) {
196
+ currentCode = text.charCodeAt(i);
197
+ previousCode = codes[codes.length - 1];
198
+ codes.push(currentCode);
199
+
200
+ if (previousCode) {
201
+ if (currentCode == previousCode + 1 || previousCode == currentCode) {
202
+ sequenceSize += 1;
203
+ } else {
204
+ sequenceSize = 0;
205
+ }
206
+ }
207
+
208
+ if (sequenceSize == 2) {
209
+ matches += 1;
210
+ }
211
+ }
212
+
213
+ return matches;
214
+ };
215
+
216
+ PasswordStrength.fn.repetitions = function(text, size) {
217
+ var count = 0;
218
+ var matches = {};
219
+ var len = text.length;
220
+ var substring;
221
+ var occurrences;
222
+ var tmpText;
223
+
224
+ for (var i = 0; i < len; i++) {
225
+ substring = text.substr(i, size);
226
+ occurrences = 0;
227
+ tmpText = text;
228
+
229
+ if (matches[substring] || substring.length < size) {
230
+ continue;
231
+ }
232
+
233
+ matches[substring] = true;
234
+
235
+ while ((i = tmpText.indexOf(substring)) != -1) {
236
+ occurrences += 1;
237
+ tmpText = tmpText.substr(i + 1);
238
+ };
239
+
240
+ if (occurrences > 1) {
241
+ count += 1;
242
+ }
243
+ }
244
+
245
+ return count;
246
+ };
247
+
248
+ PasswordStrength.fn.reversed = function(text) {
249
+ var newText = "";
250
+ var len = text.length;
251
+
252
+ for (var i = len -1; i >= 0; i--) {
253
+ newText += text.charAt(i);
254
+ }
255
+
256
+ return newText;
257
+ };
258
+
259
+ PasswordStrength.test = function(username, password) {
260
+ strength = new PasswordStrength();
261
+ strength.username = username;
262
+ strength.password = password;
263
+ strength.test();
264
+ return strength;
265
+ };
266
+
267
+ PasswordStrength.commonWords = ["000000", "010203", "1111", "11111", "111111", "11111111", "112233", "1212", "121212", "123123", "1234", "12345", "123456", "1234567", "12345678", "123456789", "1234567890", "1313", "131313", "2000", "2112", "2222", "232323", "3333", "4128", "4321", "4444", "5150", "5555", "555555", "654321", "6666", "666666", "6969", "696969", "7777", "777777", "7777777", "8675309", "987654", "aaaa", "aaaaaa", "abc123", "abcdef", "abgrtyu", "access", "access14", "action", "admin", "adobe123", "albert", "alex", "alexis", "amanda", "amateur", "andrea", "andrew", "angel", "angela", "angels", "animal", "anthony", "apollo", "apple", "apples", "arsenal", "arthur", "asdf", "asdfgh", "ashley", "asshole", "august", "austin", "azerty", "baby", "badboy", "bailey", "banana", "barney", "baseball", "batman", "beach", "bear", "beaver", "beavis", "beer", "bigcock", "bigdaddy", "bigdick", "bigdog", "bigtits", "bill", "billy", "birdie", "bitch", "bitches", "biteme", "black", "blazer", "blonde", "blondes", "blowjob", "blowme", "blue", "bond007", "bonnie", "booboo", "boobs", "booger", "boomer", "booty", "boston", "brandon", "brandy", "braves", "brazil", "brian", "bronco", "broncos", "bubba", "buddy", "bulldog", "buster", "butter", "butthead", "calvin", "camaro", "cameron", "canada", "captain", "carlos", "carter", "casper", "charles", "charlie", "cheese", "chelsea", "chester", "chevy", "chicago", "chicken", "chris", "cocacola", "cock", "coffee", "college", "compaq", "computer", "cookie", "cool", "cooper", "corvette", "cowboy", "cowboys", "cream", "crystal", "cumming", "cumshot", "cunt", "dakota", "dallas", "daniel", "danielle", "dave", "david", "debbie", "dennis", "deuseamor", "diablo", "diamond", "dick", "dirty", "doctor", "doggie", "dolphin", "dolphins", "donald", "dragon", "dreams", "driver", "eagle", "eagle1", "eagles", "edward", "einstein", "enjoy", "enter", "eric", "erotic", "extreme", "falcon", "FaMiLia", "fender", "ferrari", "fire", "firebird", "fish", "fishing", "florida", "flower", "flyers", "football", "ford", "forever", "frank", "fred", "freddy", "freedom", "fuck", "fucked", "fucker", "fucking", "fuckme", "fuckyou", "gandalf", "gateway", "gators", "gemini", "george", "giants", "ginger", "girl", "girls", "golden", "golf", "golfer", "gordon", "great", "green", "gregory", "guitar", "gunner", "hammer", "hannah", "happy", "hardcore", "harley", "heather", "hello", "helpme", "hentai", "hockey", "hooters", "horney", "horny", "hotdog", "house", "hunter", "hunting", "iceman", "iloveyou", "internet", "iwantu", "jack", "jackie", "jackson", "jaguar", "jake", "james", "japan", "jasmine", "jason", "jasper", "jennifer", "jeremy", "jessica", "jesus", "jesuscristo", "john", "johnny", "johnson", "jordan", "joseph", "joshua", "juice", "junior", "justin", "kelly", "kevin", "killer", "king", "kitty", "knight", "ladies", "lakers", "lauren", "leather", "legend", "letmein", "little", "london", "love", "lover", "lovers", "lucky", "maddog", "madison", "maggie", "magic", "magnum", "MARCELO", "marine", "mark", "marlboro", "martin", "marvin", "master", "matrix", "matt", "matthew", "maverick", "maxwell", "melissa", "member", "mercedes", "merlin", "michael", "michelle", "mickey", "midnight", "mike", "miller", "mine", "mistress", "money", "monica", "monkey", "monster", "morgan", "mother", "mountain", "movie", "muffin", "murphy", "music", "mustang", "naked", "nascar", "nathan", "naughty", "ncc1701", "newyork", "nicholas", "nicole", "ninja", "nipple", "nipples", "oliver", "orange", "ou812", "packers", "panther", "panties", "paris", "parker", "pass", "passw0rd", "password", "password1", "password12", "password123", "patrick", "paul", "peaches", "peanut", "penis", "pepper", "peter", "phantom", "phoenix", "photoshop", "player", "please", "pookie", "porn", "porno", "porsche", "power", "prince", "princess", "private", "purple", "pussies", "pussy", "qazwsx", "qwert", "qwerty", "qwertyui", "rabbit", "rachel", "racing", "raiders", "rainbow", "ranger", "rangers", "rebecca", "redskins", "redsox", "redwings", "richard", "robert", "rock", "rocket", "rosebud", "runner", "rush2112", "russia", "samantha", "sammy", "samson", "sandra", "saturn", "scooby", "scooter", "scorpio", "scorpion", "scott", "secret", "sexsex", "sexy", "shadow", "shannon", "shaved", "shit", "sierra", "silver", "skippy", "slayer", "slut", "smith", "smokey", "snoopy", "soccer", "sophie", "spanky", "sparky", "spider", "squirt", "srinivas", "star", "stars", "startrek", "starwars", "steelers", "steve", "steven", "sticky", "stupid", "success", "suckit", "summer", "sunshine", "super", "superman", "surfer", "swimming", "sydney", "taylor", "teens", "tennis", "teresa", "test", "tester", "testing", "theman", "thomas", "thunder", "thx1138", "tiffany", "tiger", "tigers", "tigger", "time", "tits", "tomcat", "topgun", "toyota", "travis", "trouble", "trustno1", "tucker", "turtle", "twitter", "united", "vagina", "victor", "victoria", "video", "viking", "viper", "voodoo", "voyager", "walter", "warrior", "welcome", "whatever", "white", "william", "willie", "wilson", "winner", "winston", "winter", "wizard", "wolf", "women", "xavier", "xxxx", "xxxxx", "xxxxxx", "xxxxxxxx", "yamaha", "yankee", "yankees", "yellow", "young", "zxcvbn", "zxcvbnm", "zzzzzz"];
268
+
269
+ return PasswordStrength;
270
+ })();