pwfoo 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ Manifest
2
+ README.rdoc
3
+ Rakefile
4
+ features/pwfoo_calculate_password_strength.feature
5
+ features/pwfoo_generate_random_password.feature
6
+ features/step_definitions/password_steps.rb
7
+ features/support/env.rb
8
+ lib/pwfoo.rb
9
+ lib/pwfoo/generate_password.rb
10
+ lib/pwfoo/password_score_calculator.rb
11
+ lib/pwfoo/password_strength.rb
12
+ lib/pwfoo/srand_seed_generator.rb
13
+ pwfoo.gemspec
14
+ spec/pwfoo/generates_password_spec.rb
15
+ spec/pwfoo/password_score_calculator_spec.rb
16
+ spec/pwfoo/random_seed_generator_spec.rb
17
+ spec/spec_helper.rb
@@ -0,0 +1,3 @@
1
+ = pwfoo
2
+
3
+ == INSTALL
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new("pwfoo", "0.1.0") do |p|
6
+ p.author = "Perry Hertler"
7
+ p.summary = "A gem that generates strong random passwords, scores the strength of passwords, and generates random seeds."
8
+ p.url = "http://github.com/perry3819/pwfoo"
9
+ p.email = "perry@hertler.org"
10
+ p.ignore_pattern = ["tmp/*", "script/*, .idea/*"]
11
+ p.development_dependencies = []
12
+ end
13
+
14
+ Dir["#File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
@@ -0,0 +1,21 @@
1
+ Feature: password manager submit password
2
+ The password manager submits a password to receive
3
+ a password strength score.
4
+
5
+ Scenario Outline: submit password
6
+ Given the password is <password>
7
+ When I submit
8
+ Then the score should be <score>
9
+
10
+ Scenarios: valid passwords
11
+ | password | score |
12
+ | ate*92. | 56 |
13
+ | a | 3 |
14
+ | | 0 |
15
+ | ate*92.U1^ | 100 |
16
+ | 123456789 | 4 |
17
+ | 0*f#8G(3i | 100 |
18
+ | 0*432tuvUi | 86 |
19
+ | 0432tuvi | 44 |
20
+ | 0432*$ | 51 |
21
+
@@ -0,0 +1,13 @@
1
+ Feature: password manager requests a random password
2
+ The password manager clicks generate_password to receive
3
+ a randomly generated strong password.
4
+
5
+ Scenario Outline: request password
6
+ Given the requested length is <length>
7
+ When I request
8
+ Then the generated length will be <gen_length>
9
+
10
+ Scenarios: valid lengths
11
+ | length | gen_length |
12
+ | 1 | 1 |
13
+ | 100 | 100 |
@@ -0,0 +1,29 @@
1
+ def password_strength
2
+ @password_strength ||= PwFoo::PasswordStrength.new
3
+ end
4
+
5
+ Given /^the password is (.*)/ do |pw|
6
+ @score = password_strength.calculate_score pw
7
+ end
8
+
9
+ When /^I submit$/ do
10
+
11
+ end
12
+
13
+ Then /^the score should be (.*)/ do |expected_score|
14
+ @score.should == expected_score.to_i
15
+ end
16
+
17
+ Given /^the requested length is (.*)/ do |length|
18
+ @gen_password = PwFoo::GeneratePassword.new(length.to_i).generate
19
+ end
20
+
21
+ When /^I request$/ do
22
+
23
+ end
24
+
25
+ Then /^the generated length will be (.*)/ do | expected_length |
26
+ expected_length.to_i.should == @gen_password.length
27
+ end
28
+
29
+
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH << File.join(File.dirname(__FILE__),"..","..","lib")
2
+ require 'pwfoo'
3
+ require 'spec/expectations'
4
+ require 'spec/stubs/cucumber'
@@ -0,0 +1,4 @@
1
+ require 'pwfoo/password_strength'
2
+ require 'pwfoo/password_score_calculator'
3
+ require 'pwfoo/generate_password'
4
+ require 'pwfoo/srand_seed_generator'
@@ -0,0 +1,48 @@
1
+ module PwFoo
2
+ class GeneratePassword
3
+ LOWER_CASE = 'lower_case'
4
+ UPPER_CASE = 'upper_case'
5
+ NUMBERS = 'numbers'
6
+ SPECIALS = 'specials'
7
+
8
+ @@character_pool = {
9
+ LOWER_CASE => ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'],
10
+ UPPER_CASE => ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],
11
+ NUMBERS => ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
12
+ SPECIALS => ['!', '@', '#', '$', '%', '^', '*', '_', '-', '*', '(', ')']
13
+ }
14
+
15
+ def initialize(length = 10, *allowed_types)
16
+ @length = length
17
+ @allowed_types = allowed_types == nil || 0 == allowed_types.length ? [LOWER_CASE, UPPER_CASE, NUMBERS] : allowed_types
18
+ @pw_strength_finder = PasswordStrength.new
19
+ srand(SrandSeedGenerator.new().get_next_seed)
20
+ end
21
+
22
+ def generate_with_min_strength(min_strength)
23
+ gen = nil
24
+ while gen == nil || min_strength > @pw_strength_finder.calculate_score(gen) do
25
+ gen = generate
26
+ end
27
+ gen
28
+ end
29
+
30
+ def generate
31
+ gen_pw = ''
32
+ @length.times { |i|
33
+ gen_pw.concat next_char
34
+ }
35
+ gen_pw
36
+ end
37
+
38
+ def next_char
39
+ ta = next_type_array
40
+ ta[rand(ta.length)]
41
+ end
42
+
43
+ def next_type_array
44
+ @@character_pool[@allowed_types[rand(@allowed_types.length)]]
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,180 @@
1
+ module PwFoo
2
+ class PasswordScoreCalculator
3
+ SYMBOLS_REGEX = /[^a-zA-Z0-9_]/
4
+ LETTERS_REGEX = /[A-Za-z]/
5
+ UPPER_CASE_REGEX = /[A-Z]/
6
+ LOWER_CASE_REGEX = /[a-z]/
7
+ NUMBERS_REGEX = /\d/
8
+
9
+ def initialize(word)
10
+ if word == nil then
11
+ @word = ''
12
+ else
13
+ @word = word
14
+ end
15
+ end
16
+
17
+ def number_of_characters_score
18
+ 4 * @word.length
19
+ end
20
+
21
+ def upper_case_letters_score
22
+ case_letters_score(UPPER_CASE_REGEX)
23
+ end
24
+
25
+ def symbols_score
26
+ zero_if_empty{6 * count(SYMBOLS_REGEX)}
27
+ end
28
+
29
+ def numbers_score
30
+ return zero_if_empty{
31
+ count = count(NUMBERS_REGEX)
32
+ count < @word.length ? 4 * count : 0
33
+ }
34
+ end
35
+
36
+ def repeat_characters_deduction
37
+ repeats = _consecutive_count {|last, current| current == last}
38
+ - (repeats * (repeats - 1))
39
+ end
40
+
41
+ def consecutive_numbers_deduction
42
+ regex = NUMBERS_REGEX
43
+ repeats = _consecutive_count {|last, current| nil != current && nil != last && current.chr =~ regex && last.chr =~ regex}
44
+ return - (repeats * 2)
45
+ end
46
+
47
+ def consecutive_upper_case_letters_deduction
48
+ _consecutive_case_letters_deduction(UPPER_CASE_REGEX)
49
+ end
50
+
51
+ def consecutive_lower_case_letters_deduction
52
+ _consecutive_case_letters_deduction(LOWER_CASE_REGEX)
53
+ end
54
+
55
+ def _consecutive_case_letters_deduction(regex)
56
+ repeats = _consecutive_count {|last, current| nil != current && nil != last && current.chr =~ regex && last.chr =~ regex}
57
+ - (repeats * 2)
58
+ end
59
+
60
+ def sequential_letters_deduction
61
+ repeats = _three_consecutive_count(lambda {|first, second, third|
62
+ consec = false
63
+ if nil != first && first.chr =~ LETTERS_REGEX && nil != second && second.chr =~ LETTERS_REGEX && nil != third && third.chr =~ LETTERS_REGEX then
64
+ consec = _are_consecutive first.chr.downcase[0], second.chr.downcase[0], third.chr.downcase[0]
65
+ end
66
+ return consec
67
+ })
68
+ - (repeats * 3)
69
+ end
70
+
71
+ def sequential_numbers_deduction
72
+ repeats = _three_consecutive_count(lambda {|first, second, third|
73
+ consec = false
74
+ if nil != first && first.chr =~ NUMBERS_REGEX && nil != second && second.chr =~ NUMBERS_REGEX && nil != third && first.chr =~ NUMBERS_REGEX then
75
+ consec = _are_consecutive first, second, third
76
+ end
77
+ consec
78
+ })
79
+ - (repeats * 3)
80
+ end
81
+
82
+ def _are_consecutive(first, second, third)
83
+ (second == (first + 1) && third == (second + 1)) || (second == (first -1) && third == (second -1))
84
+ end
85
+
86
+ def _three_consecutive_count(is_consecutive)
87
+ repeats = 0
88
+ first = nil, second = nil, third = nil
89
+
90
+ 0.upto(@word.length - 1) { |i|
91
+ first = second
92
+ second = third
93
+ third = @word[i]
94
+ if is_consecutive.call(first, second, third) then
95
+ repeats = repeats + 1
96
+ end
97
+ }
98
+
99
+ repeats
100
+ end
101
+
102
+ def _consecutive_count(&is_consecutive)
103
+ repeats = 0
104
+
105
+ cur_char = nil
106
+ 0.upto(@word.length - 1) { |i|
107
+ if is_consecutive.call(cur_char, @word[i]) then
108
+ repeats = repeats + 1
109
+ end
110
+ cur_char = @word[i]
111
+ }
112
+
113
+ repeats
114
+ end
115
+
116
+ def letters_only_deduction
117
+ only_deduction(LETTERS_REGEX)
118
+ end
119
+
120
+ def numbers_only_deduction
121
+ only_deduction(NUMBERS_REGEX)
122
+ end
123
+
124
+ def only_deduction(regex)
125
+ zero_if_empty{
126
+ @word.length == count(regex) ? (- @word.length) : 0
127
+ }
128
+ end
129
+
130
+ def lower_case_letters_score
131
+ case_letters_score(/[a-z]/)
132
+ end
133
+
134
+ def case_letters_score(regex)
135
+ zero_if_empty {
136
+ count = count(regex)
137
+ count > 0 ? ((@word.length - count(regex)) * 2) : 0
138
+ }
139
+ end
140
+
141
+ def zero_if_empty(&calculator)
142
+ 0 == number_of_characters_score ? 0 : calculator.call
143
+ end
144
+
145
+ def middle_numbers_or_symbols_score
146
+ middle = @word[1, @word.length-2]
147
+ @word.length < 3 ? 0 : (2 * (count(SYMBOLS_REGEX, middle) + count(NUMBERS_REGEX, middle)))
148
+ end
149
+
150
+ def count(regex, count_word=@word)
151
+ count_word.scan(regex).length
152
+ end
153
+
154
+ def requirements_score
155
+ 0
156
+ end
157
+
158
+ def print_all
159
+ puts '=============================================================='
160
+ puts 'Score for word: ' << @word
161
+ puts 'Number of Characters: ' << number_of_characters_score.to_s
162
+ puts 'Uppercase Letters: ' << upper_case_letters_score.to_s
163
+ puts 'Lowercase Letters: ' << lower_case_letters_score.to_s
164
+ puts 'Numbers: ' << numbers_score.to_s
165
+ puts 'Symbols: ' << symbols_score.to_s
166
+ puts 'Middle Numbers or Symbols: ' << middle_numbers_or_symbols_score.to_s
167
+ puts 'Requirements: ' << requirements_score.to_s
168
+ puts 'Letters Only: ' << letters_only_deduction.to_s
169
+ puts 'Numbers Only: ' << numbers_only_deduction.to_s
170
+ puts 'Repeat Characters: ' << repeat_characters_deduction.to_s
171
+ puts 'Consecutive Uppercase Letters: ' << consecutive_upper_case_letters_deduction.to_s
172
+ puts 'Consecutive Lowercase Letters: ' << consecutive_lower_case_letters_deduction.to_s
173
+ puts 'Consecutive Numbers: ' << consecutive_numbers_deduction.to_s
174
+ puts 'Sequential Letters: ' << sequential_letters_deduction.to_s
175
+ puts 'Sequential Numbers: ' << sequential_numbers_deduction.to_s
176
+ puts '=============================================================='
177
+ end
178
+
179
+ end
180
+ end
@@ -0,0 +1,16 @@
1
+ module PwFoo
2
+ class PasswordStrength
3
+ def initialize
4
+ end
5
+
6
+ def calculate_score(pw)
7
+ sc = PasswordScoreCalculator.new(pw)
8
+ total = sc.number_of_characters_score + sc.upper_case_letters_score + sc.lower_case_letters_score + sc.numbers_score + sc.symbols_score + sc.middle_numbers_or_symbols_score + sc.requirements_score + sc.letters_only_deduction + sc.numbers_only_deduction + sc.repeat_characters_deduction + sc.consecutive_upper_case_letters_deduction + sc.consecutive_lower_case_letters_deduction + sc.consecutive_numbers_deduction + sc.sequential_letters_deduction + sc.sequential_numbers_deduction
9
+ total > 100 ? 100 : total
10
+ end
11
+
12
+ def print_score(pw)
13
+ PasswordScoreCalculator.new(pw).print_all
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,20 @@
1
+ module PwFoo
2
+ require 'digest/md5'
3
+
4
+ class SrandSeedGenerator
5
+ def initialize
6
+ end
7
+
8
+ def get_next_seed
9
+ time_in_micro = Time.new().to_f * 100000
10
+ checksum = _get_checksum
11
+
12
+ time_in_micro * time_in_micro + checksum.to_i
13
+ end
14
+
15
+ def _get_checksum
16
+ Digest::MD5.hexdigest(`ps axww | gzip`)
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{pwfoo}
5
+ s.version = "0.1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Perry Hertler"]
9
+ s.date = %q{2009-11-10}
10
+ s.description = %q{A gem that generates strong random passwords, scores the strength of passwords, and generates random seeds.}
11
+ s.email = %q{perry@hertler.org}
12
+ s.extra_rdoc_files = ["README.rdoc", "lib/pwfoo.rb", "lib/pwfoo/generate_password.rb", "lib/pwfoo/password_score_calculator.rb", "lib/pwfoo/password_strength.rb", "lib/pwfoo/srand_seed_generator.rb"]
13
+ s.files = ["Manifest", "README.rdoc", "Rakefile", "features/pwfoo_calculate_password_strength.feature", "features/pwfoo_generate_random_password.feature", "features/step_definitions/password_steps.rb", "features/support/env.rb", "lib/pwfoo.rb", "lib/pwfoo/generate_password.rb", "lib/pwfoo/password_score_calculator.rb", "lib/pwfoo/password_strength.rb", "lib/pwfoo/srand_seed_generator.rb", "pwfoo.gemspec", "spec/pwfoo/generates_password_spec.rb", "spec/pwfoo/password_score_calculator_spec.rb", "spec/pwfoo/random_seed_generator_spec.rb", "spec/spec_helper.rb"]
14
+ s.homepage = %q{http://github.com/perry3819/pwfoo}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Pwfoo", "--main", "README.rdoc"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{pwfoo}
18
+ s.rubygems_version = %q{1.3.5}
19
+ s.summary = %q{A gem that generates strong random passwords, scores the strength of passwords, and generates random seeds.}
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
+ else
27
+ end
28
+ else
29
+ end
30
+ end
@@ -0,0 +1,88 @@
1
+ require File.join(File.dirname(__FILE__), "..", "spec_helper")
2
+
3
+ module PwFoo
4
+ describe GeneratePassword do
5
+ include GeneratePasswordHelper
6
+
7
+ before(:all) do
8
+ Spec::Matchers.define :be_greater_than_or_equal do |min_score|
9
+ match do |score|
10
+ score >= min_score
11
+ end
12
+ end
13
+ end
14
+
15
+ before(:each) do
16
+
17
+ end
18
+
19
+ context "with defaults" do
20
+ it "should have length of 7" do
21
+ PwFoo::GeneratePassword.new(7).generate.length.should == 7
22
+ end
23
+ it "should have length of 0" do
24
+ PwFoo::GeneratePassword.new(0).generate.length.should == 0
25
+ end
26
+ it "should have length of 1" do
27
+ PwFoo::GeneratePassword.new(1).generate.length.should == 1
28
+ end
29
+ it "should have length of 100" do
30
+ PwFoo::GeneratePassword.new(100).generate.length.should == 100
31
+ end
32
+ context "with just letters" do
33
+ def length_of_nonletters (word)
34
+ word.scan(/[^A-Za-z]/).length
35
+ end
36
+
37
+ it "should contain no numbers or specials" do
38
+ gw = PwFoo::GeneratePassword.new(12, PwFoo::GeneratePassword::LOWER_CASE, PwFoo::GeneratePassword::UPPER_CASE)
39
+ length_of_nonletters(gw.generate).should == 0
40
+ length_of_nonletters(gw.generate).should == 0
41
+ length_of_nonletters(gw.generate).should == 0
42
+ length_of_nonletters(gw.generate).should == 0
43
+ end
44
+ end
45
+ context "with just numbers" do
46
+ def length_of_nonnumbers(word)
47
+ word.scan(/[^0-9]/).length
48
+ end
49
+
50
+ it "should contain no letters or specials" do
51
+ gw = PwFoo::GeneratePassword.new(12, PwFoo::GeneratePassword::NUMBERS)
52
+ length_of_nonnumbers(gw.generate).should == 0
53
+ length_of_nonnumbers(gw.generate).should == 0
54
+ length_of_nonnumbers(gw.generate).should == 0
55
+ length_of_nonnumbers(gw.generate).should == 0
56
+ end
57
+ end
58
+ context "with just specials" do
59
+ def length_of_nonspecials(word)
60
+ word.scan(/[A-Za-z0-9]/).length
61
+ end
62
+
63
+ it "should contain no letters or specials" do
64
+ gw = PwFoo::GeneratePassword.new(12, PwFoo::GeneratePassword::SPECIALS)
65
+ length_of_nonspecials(gw.generate).should == 0
66
+ length_of_nonspecials(gw.generate).should == 0
67
+ length_of_nonspecials(gw.generate).should == 0
68
+ length_of_nonspecials(gw.generate).should == 0
69
+ end
70
+ end
71
+ context "with minimum strength" do
72
+ def generate_with_min_strength(min_s)
73
+ gp = PwFoo::GeneratePassword.new(12, PwFoo::GeneratePassword::SPECIALS, PwFoo::GeneratePassword::LOWER_CASE, PwFoo::GeneratePassword::UPPER_CASE, PwFoo::GeneratePassword::NUMBERS)
74
+ gp.generate_with_min_strength min_s
75
+ end
76
+
77
+ def calc_strength(word)
78
+ PasswordStrength.new.calculate_score(word)
79
+ end
80
+
81
+ it "should have a strength greater than 70" do
82
+ pw = generate_with_min_strength(70)
83
+ calc_strength(pw).should be_greater_than_or_equal( 70 )
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,221 @@
1
+ require File.join(File.dirname(__FILE__), "..", "spec_helper")
2
+
3
+ module PwFoo
4
+ describe PasswordScoreCalculator do
5
+ before(:each) do
6
+ @score_calculator = PwFoo::PasswordScoreCalculator.new('a4bV%(z')
7
+ @nil_score_calculator = PwFoo::PasswordScoreCalculator.new(nil)
8
+ end
9
+ context "with upper case letters" do
10
+ it "should return 12" do
11
+ @score_calculator.upper_case_letters_score.should == 12
12
+ end
13
+ end
14
+ context "with nil password" do
15
+ it "should return 0" do
16
+ @nil_score_calculator.upper_case_letters_score.should == 0
17
+ @nil_score_calculator.lower_case_letters_score.should == 0
18
+ @nil_score_calculator.symbols_score.should == 0
19
+ @nil_score_calculator.middle_numbers_or_symbols_score.should == 0
20
+ @nil_score_calculator.repeat_characters_deduction.should == 0
21
+ @nil_score_calculator.consecutive_upper_case_letters_deduction.should == 0
22
+ @nil_score_calculator.consecutive_lower_case_letters_deduction.should == 0
23
+ @nil_score_calculator.consecutive_numbers_deduction.should == 0
24
+ @nil_score_calculator.sequential_letters_deduction.should == 0
25
+ @nil_score_calculator.sequential_numbers_deduction.should == 0
26
+ @nil_score_calculator.numbers_only_deduction.should == 0
27
+ @nil_score_calculator.letters_only_deduction.should == 0
28
+ @nil_score_calculator.numbers_score.should == 0
29
+ @nil_score_calculator.number_of_characters_score.should == 0
30
+ end
31
+ end
32
+ context "with no upper case letters" do
33
+ it "should return 0" do
34
+ PwFoo::PasswordScoreCalculator.new('ate*92.').upper_case_letters_score.should == 0
35
+ end
36
+ end
37
+ context "with lower case letters" do
38
+ it "should return 8" do
39
+ @score_calculator.lower_case_letters_score.should == 8
40
+ end
41
+ end
42
+ context "with no lower case letters" do
43
+ it "should return 0" do
44
+ PwFoo::PasswordScoreCalculator.new('AA').lower_case_letters_score.should == 0
45
+ end
46
+ end
47
+ context "with symbols" do
48
+ it "should return 12" do
49
+ @score_calculator.symbols_score.should == 12
50
+ end
51
+ end
52
+ context "with no symbols" do
53
+ it "should return 0" do
54
+ PwFoo::PasswordScoreCalculator.new('AAa').symbols_score.should == 0
55
+ end
56
+ end
57
+ context "with middle numbers or symbols" do
58
+ it "should return 6" do
59
+ @score_calculator.middle_numbers_or_symbols_score.should == 6
60
+ end
61
+ end
62
+ context "with no middle numbers or symbols" do
63
+ it "should return 0" do
64
+ PwFoo::PasswordScoreCalculator.new('AAa').middle_numbers_or_symbols_score.should == 0
65
+ end
66
+ end
67
+ context "with no requirements score" do
68
+ it "should return 0" do
69
+ @score_calculator.requirements_score.should == 0
70
+ end
71
+ end
72
+ context "with repeat characters" do
73
+ it "should return -2" do
74
+ PwFoo::PasswordScoreCalculator.new('8a77bbw').repeat_characters_deduction.should == -2
75
+ end
76
+ it "should return -6" do
77
+ PwFoo::PasswordScoreCalculator.new('8a777bbw').repeat_characters_deduction.should == -6
78
+ end
79
+ end
80
+ context "with no repeat characters" do
81
+ it "should return 0" do
82
+ @score_calculator.repeat_characters_deduction.should == 0
83
+ end
84
+ end
85
+ context "with consecutive upper case" do
86
+ it "should return -2" do
87
+ PwFoo::PasswordScoreCalculator.new('8a77BBw').consecutive_upper_case_letters_deduction.should == -2
88
+ end
89
+ it "should return -8" do
90
+ PwFoo::PasswordScoreCalculator.new('8aBB777CCCCbbw').consecutive_upper_case_letters_deduction.should == -8
91
+ end
92
+ end
93
+ context "with no consecutive upper case" do
94
+ it "should return 0" do
95
+ @score_calculator.consecutive_upper_case_letters_deduction.should == 0
96
+ end
97
+ end
98
+ context "with consecutive lower case" do
99
+ it "should return -2" do
100
+ PwFoo::PasswordScoreCalculator.new('8a77zzW').consecutive_lower_case_letters_deduction.should == -2
101
+ end
102
+ it "should return -14" do
103
+ PwFoo::PasswordScoreCalculator.new('8abe777dddbbw').consecutive_lower_case_letters_deduction.should == -14
104
+ end
105
+ end
106
+ context "with no consecutive lower case" do
107
+ it "should return 0" do
108
+ @score_calculator.consecutive_lower_case_letters_deduction.should == 0
109
+ end
110
+ end
111
+ context "with consecutive numbers" do
112
+ it "should return -2" do
113
+ PwFoo::PasswordScoreCalculator.new('8a77zzW').consecutive_numbers_deduction.should == -2
114
+ end
115
+ it "should return -10" do
116
+ PwFoo::PasswordScoreCalculator.new('8abe777dddbbw8361').consecutive_numbers_deduction.should == -10
117
+ end
118
+ it "should return -16" do
119
+ PwFoo::PasswordScoreCalculator.new('123456789').consecutive_numbers_deduction.should == -16
120
+ end
121
+ end
122
+ context "with no consecutive numbers" do
123
+ it "should return 0" do
124
+ @score_calculator.consecutive_numbers_deduction.should == 0
125
+ end
126
+ it "should return 0" do
127
+ PwFoo::PasswordScoreCalculator.new('0*f#8G(3i').consecutive_numbers_deduction.should == 0
128
+ end
129
+ end
130
+ context "with sequential letters" do
131
+ it "should return -3" do
132
+ PwFoo::PasswordScoreCalculator.new('aBc872ai').sequential_letters_deduction.should == -3
133
+ end
134
+ it "should return -6" do
135
+ PwFoo::PasswordScoreCalculator.new('8abe777tSrQdddbbw').sequential_letters_deduction.should == -6
136
+ end
137
+ end
138
+ context "with no sequential letters" do
139
+ it "should return 0" do
140
+ @score_calculator.sequential_letters_deduction.should == 0
141
+ end
142
+ end
143
+ context "with sequential numbers" do
144
+ it "should return -3" do
145
+ PwFoo::PasswordScoreCalculator.new('aBc854372ai').sequential_numbers_deduction.should == -3
146
+ end
147
+ it "should return -3" do
148
+ PwFoo::PasswordScoreCalculator.new('8abe77789tSrQdddbbw').sequential_numbers_deduction.should == -3
149
+ end
150
+ it "should return -12" do
151
+ PwFoo::PasswordScoreCalculator.new('8abe77789tSr56789Qdddbbw').sequential_numbers_deduction.should == -12
152
+ end
153
+ it "should return -21" do
154
+ PwFoo::PasswordScoreCalculator.new('123456789').sequential_numbers_deduction.should == -21
155
+ end
156
+ end
157
+ context "with no sequential numbers" do
158
+ it "should return 0" do
159
+ @score_calculator.sequential_numbers_deduction.should == 0
160
+ end
161
+ it "should return 0" do
162
+ PwFoo::PasswordScoreCalculator.new('0*f#8G(3i').sequential_numbers_deduction.should == 0
163
+ end
164
+ end
165
+ context "with numbers only" do
166
+ it "should return -6" do
167
+ PwFoo::PasswordScoreCalculator.new('123456').numbers_only_deduction.should == -6
168
+ end
169
+ it "should return -9" do
170
+ PwFoo::PasswordScoreCalculator.new('123456789').numbers_only_deduction.should == -9
171
+ end
172
+ end
173
+ context "with no sequential numbers" do
174
+ it "should return 0" do
175
+ @score_calculator.numbers_only_deduction.should == 0
176
+ end
177
+ it "should return 0" do
178
+ PwFoo::PasswordScoreCalculator.new('0*f#8G(3i').numbers_only_deduction.should == 0
179
+ end
180
+ end
181
+ context "with letters only" do
182
+ it "should return -5" do
183
+ PwFoo::PasswordScoreCalculator.new('abcde').letters_only_deduction.should == -5
184
+ end
185
+ end
186
+ context "with no letters" do
187
+ it "should return 0" do
188
+ @score_calculator.letters_only_deduction.should == 0
189
+ end
190
+ end
191
+ context "with numbers score" do
192
+ it "should return 4" do
193
+ @score_calculator.numbers_score.should == 4
194
+ end
195
+ end
196
+ context "with no numbers score" do
197
+ it "should return 0" do
198
+ PwFoo::PasswordScoreCalculator.new('123456789').numbers_score.should == 0
199
+ end
200
+ end
201
+ context "with characters score" do
202
+ it "should return 28" do
203
+ @score_calculator.number_of_characters_score.should == 28
204
+ end
205
+ end
206
+ context "with count" do
207
+ it "should return 4" do
208
+ @score_calculator.count(/[A-Za-z]/).should == 4
209
+ end
210
+ it "should return 1" do
211
+ @score_calculator.count(/\d/).should == 1
212
+ end
213
+ it "should return 2" do
214
+ @score_calculator.count(/\W/).should == 2
215
+ end
216
+ it "should return 2" do
217
+ @score_calculator.count(/[^a-zA-Z0-9_]/).should == 2
218
+ end
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,19 @@
1
+ require File.join(File.dirname(__FILE__), "..", "spec_helper")
2
+
3
+ module PwFoo
4
+ describe SrandSeedGenerator do
5
+ before(:each) do
6
+ @seed_gen = SrandSeedGenerator.new
7
+ end
8
+ context "with different seeds" do
9
+ it "should not be equal" do
10
+ @seed_gen.get_next_seed.should_not == @seed_gen.get_next_seed
11
+ end
12
+ end
13
+ context "with checksum" do
14
+ it "should not be nil" do
15
+ @seed_gen._get_checksum.should_not be_nil
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ $LOAD_PATH << File.join(File.dirname(__FILE__),"..","lib")
2
+ require 'spec'
3
+ require 'pwfoo'
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pwfoo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Perry Hertler
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-10 00:00:00 -06:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: A gem that generates strong random passwords, scores the strength of passwords, and generates random seeds.
17
+ email: perry@hertler.org
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ - lib/pwfoo.rb
25
+ - lib/pwfoo/generate_password.rb
26
+ - lib/pwfoo/password_score_calculator.rb
27
+ - lib/pwfoo/password_strength.rb
28
+ - lib/pwfoo/srand_seed_generator.rb
29
+ files:
30
+ - Manifest
31
+ - README.rdoc
32
+ - Rakefile
33
+ - features/pwfoo_calculate_password_strength.feature
34
+ - features/pwfoo_generate_random_password.feature
35
+ - features/step_definitions/password_steps.rb
36
+ - features/support/env.rb
37
+ - lib/pwfoo.rb
38
+ - lib/pwfoo/generate_password.rb
39
+ - lib/pwfoo/password_score_calculator.rb
40
+ - lib/pwfoo/password_strength.rb
41
+ - lib/pwfoo/srand_seed_generator.rb
42
+ - pwfoo.gemspec
43
+ - spec/pwfoo/generates_password_spec.rb
44
+ - spec/pwfoo/password_score_calculator_spec.rb
45
+ - spec/pwfoo/random_seed_generator_spec.rb
46
+ - spec/spec_helper.rb
47
+ has_rdoc: true
48
+ homepage: http://github.com/perry3819/pwfoo
49
+ licenses: []
50
+
51
+ post_install_message:
52
+ rdoc_options:
53
+ - --line-numbers
54
+ - --inline-source
55
+ - --title
56
+ - Pwfoo
57
+ - --main
58
+ - README.rdoc
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "1.2"
72
+ version:
73
+ requirements: []
74
+
75
+ rubyforge_project: pwfoo
76
+ rubygems_version: 1.3.5
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: A gem that generates strong random passwords, scores the strength of passwords, and generates random seeds.
80
+ test_files: []
81
+