password_strength 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +19 -2
- data/README.rdoc +1 -1
- data/lib/jquery.strength.js +20 -9
- data/lib/password_strength/base.rb +26 -3
- data/lib/password_strength/version.rb +1 -1
- data/test/jquery_strength_test.js +21 -0
- data/test/password_strength_test.rb +23 -0
- metadata +2 -2
data/CHANGELOG.rdoc
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
= Changelog
|
2
2
|
|
3
|
-
== March 5 2010
|
3
|
+
== 0.1.0 - March 5 2010
|
4
4
|
|
5
|
-
*
|
5
|
+
* First release
|
6
|
+
|
7
|
+
== 0.1.1 - March 5 2010
|
8
|
+
|
9
|
+
* Added JavaScript implementation
|
10
|
+
|
11
|
+
== 0.1.2 - March 5 2010
|
12
|
+
|
13
|
+
* Added jQuery plugin
|
14
|
+
|
15
|
+
== 0.1.3 - March 5 2010
|
16
|
+
|
17
|
+
* Added localized error messages for +pt+ and +en+
|
18
|
+
|
19
|
+
== 0.1.4 - March 8 2010
|
20
|
+
|
21
|
+
* jQuery function can accept string instead of selectors
|
22
|
+
* Added repetition penalization
|
data/README.rdoc
CHANGED
@@ -9,6 +9,7 @@ Validates the strength of a password according to several rules:
|
|
9
9
|
* combination of numbers, letters and symbols
|
10
10
|
* password contains username
|
11
11
|
* sequences (123, abc, aaa)
|
12
|
+
* repetitions
|
12
13
|
|
13
14
|
Some results:
|
14
15
|
|
@@ -105,7 +106,6 @@ Get the files:
|
|
105
106
|
|
106
107
|
= TO-DO
|
107
108
|
|
108
|
-
* Detect repetitions
|
109
109
|
* Rake task to get the latest JavaScript file
|
110
110
|
|
111
111
|
= License
|
data/lib/jquery.strength.js
CHANGED
@@ -1,19 +1,32 @@
|
|
1
1
|
(function($){
|
2
2
|
$.strength = function(username, password, callback) {
|
3
|
-
|
4
|
-
|
3
|
+
var usernameField = $(username);
|
4
|
+
var passwordField = $(password);
|
5
5
|
var strength = new PasswordStrength();
|
6
6
|
callback = callback || $.strength.callback;
|
7
7
|
|
8
8
|
var handler = function(){
|
9
|
-
strength.username = $(
|
10
|
-
|
9
|
+
strength.username = $(usernameField).val();
|
10
|
+
|
11
|
+
if ($(usernameField).length == 0) {
|
12
|
+
strength.username = username;
|
13
|
+
}
|
14
|
+
|
15
|
+
strength.password = $(passwordField).val();
|
16
|
+
|
17
|
+
if ($(passwordField).length == 0) {
|
18
|
+
strength.password = password;
|
19
|
+
}
|
20
|
+
|
11
21
|
strength.test();
|
12
|
-
callback(
|
22
|
+
callback(usernameField, passwordField, strength);
|
13
23
|
};
|
14
24
|
|
15
|
-
$(
|
16
|
-
$(
|
25
|
+
$(usernameField).keydown(handler);
|
26
|
+
$(usernameField).keyup(handler);
|
27
|
+
|
28
|
+
$(passwordField).keydown(handler);
|
29
|
+
$(passwordField).keyup(handler);
|
17
30
|
};
|
18
31
|
|
19
32
|
$.extend($.strength, {
|
@@ -31,8 +44,6 @@
|
|
31
44
|
.removeClass("strong")
|
32
45
|
.addClass(strength.status)
|
33
46
|
.attr("src", $.strength[strength.status + "Image"]);
|
34
|
-
|
35
|
-
console.debug($.strength[strength.status + "Image"])
|
36
47
|
},
|
37
48
|
weakImage: "/images/weak.png",
|
38
49
|
goodImage: "/images/good.png",
|
@@ -98,8 +98,12 @@ module PasswordStrength
|
|
98
98
|
score = -15 if password =~ /#{Regexp.escape(username)}/
|
99
99
|
end
|
100
100
|
when :sequences then
|
101
|
-
score = -15 *
|
102
|
-
score += -15 *
|
101
|
+
score = -15 * sequences(password)
|
102
|
+
score += -15 * sequences(password.to_s.reverse)
|
103
|
+
when :repetitions then
|
104
|
+
score += -(repetitions(password, 2) * 4)
|
105
|
+
score += -(repetitions(password, 3) * 3)
|
106
|
+
score += -(repetitions(password, 4) * 2)
|
103
107
|
end
|
104
108
|
|
105
109
|
score
|
@@ -118,6 +122,7 @@ module PasswordStrength
|
|
118
122
|
@score += score_for(:only_numbers)
|
119
123
|
@score += score_for(:username)
|
120
124
|
@score += score_for(:sequences)
|
125
|
+
@score += score_for(:repetitions)
|
121
126
|
|
122
127
|
@score = 0 if score < 0
|
123
128
|
@score = 100 if score > 100
|
@@ -129,7 +134,25 @@ module PasswordStrength
|
|
129
134
|
score
|
130
135
|
end
|
131
136
|
|
132
|
-
def
|
137
|
+
def repetitions(text, size) # :nodoc:
|
138
|
+
count = 0
|
139
|
+
matches = []
|
140
|
+
|
141
|
+
0.upto(text.size - 1) do |i|
|
142
|
+
substring = text[i, size]
|
143
|
+
|
144
|
+
next if matches.include?(substring) || substring.size < size
|
145
|
+
|
146
|
+
matches << substring
|
147
|
+
occurrences = text.scan(substring).length
|
148
|
+
|
149
|
+
count += 1 if occurrences > 1
|
150
|
+
end
|
151
|
+
|
152
|
+
count
|
153
|
+
end
|
154
|
+
|
155
|
+
def sequences(text) # :nodoc:
|
133
156
|
matches = 0
|
134
157
|
sequence_size = 0
|
135
158
|
bytes = []
|
@@ -71,4 +71,25 @@ new Test.Unit.Runner({
|
|
71
71
|
assertEqual(1, $("img.strong").length);
|
72
72
|
assertEqual("/images/strong.png", $("img.strength").attr("src"));
|
73
73
|
}},
|
74
|
+
|
75
|
+
// Missing username element: use selector as text
|
76
|
+
testMissingUsernameElementUseSelectorAsText: function() { with(this) {
|
77
|
+
$("#password").val("^P4ssw0rd$");
|
78
|
+
$.strength("root", "#password", function(username, password, strength){
|
79
|
+
assertEqual("root", strength.username);
|
80
|
+
assertEqual("^P4ssw0rd$", strength.password);
|
81
|
+
});
|
82
|
+
|
83
|
+
$("#password").trigger("keydown");
|
84
|
+
}},
|
85
|
+
|
86
|
+
// Missing password element: use selector as text
|
87
|
+
testMissingPasswordElementUseSelectorAsText: function() { with(this) {
|
88
|
+
$.strength("#username", "mypass", function(username, password, strength){
|
89
|
+
assertEqual("johndoe", strength.username);
|
90
|
+
assertEqual("mypass", strength.password);
|
91
|
+
});
|
92
|
+
|
93
|
+
$("#username").trigger("keydown");
|
94
|
+
}}
|
74
95
|
});
|
@@ -155,6 +155,14 @@ class TestPasswordStrength < Test::Unit::TestCase
|
|
155
155
|
assert_equal -100, @strength.score_for(:password_size)
|
156
156
|
end
|
157
157
|
|
158
|
+
def test_penalize_repetitions
|
159
|
+
# 2-chars: ab, bc, cd, da (4 * 4 = 16)
|
160
|
+
# 3-chars: abc, bcd, cda, dab (4 * 3 = 12)
|
161
|
+
# 4-chars: abcd, bcda, cdab, dabc (4 * 2 = 8)
|
162
|
+
@strength.password = "abcdabcdabcd"
|
163
|
+
assert_equal -36, @strength.score_for(:repetitions)
|
164
|
+
end
|
165
|
+
|
158
166
|
def test_password_length
|
159
167
|
@strength.password = "12345"
|
160
168
|
assert_equal 20, @strength.score_for(:password_size)
|
@@ -189,4 +197,19 @@ class TestPasswordStrength < Test::Unit::TestCase
|
|
189
197
|
@strength.password = "a$"
|
190
198
|
assert_equal 15, @strength.score_for(:symbols_chars)
|
191
199
|
end
|
200
|
+
|
201
|
+
def test_two_chars_repetition
|
202
|
+
# expected: 11, 22, 12
|
203
|
+
assert_equal 3, @strength.repetitions("11221122", 2)
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_three_chars_repetition
|
207
|
+
# expected: 123, 231, 312
|
208
|
+
assert_equal 3, @strength.repetitions("123123123", 3)
|
209
|
+
end
|
210
|
+
|
211
|
+
def test_four_chars_repetition
|
212
|
+
# expected: abcd, bcda, cdab, dabc
|
213
|
+
assert_equal 4, @strength.repetitions("abcdabcdabcd", 4)
|
214
|
+
end
|
192
215
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: password_strength
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nando Vieira
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-03-
|
12
|
+
date: 2010-03-08 00:00:00 -03:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|