pwfoo 0.1.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.
@@ -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
+