strong_password 0.0.4 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,31 +2,29 @@ require 'spec_helper'
2
2
 
3
3
  module StrongPassword
4
4
  describe QwertyAdjuster do
5
- describe '#is_strong?' do
6
- let(:subject) { QwertyAdjuster.new('password') }
5
+ subject(:qwerty_adjuster) { QwertyAdjuster.new(entropy_threshhold: 0) }
7
6
 
7
+ describe '#is_strong?' do
8
8
  it 'returns true if the calculated entropy is >= the minimum' do
9
- subject.stub(adjusted_entropy: 18)
10
- expect(subject.is_strong?).to be_true
9
+ allow(subject).to receive_messages(adjusted_entropy: 18)
10
+ expect(subject.is_strong?('password')).to be_truthy
11
11
  end
12
-
12
+
13
13
  it 'returns false if the calculated entropy is < the minimum' do
14
- subject.stub(adjusted_entropy: 17)
15
- expect(subject.is_strong?).to be_false
14
+ allow(subject).to receive_messages(adjusted_entropy: 17)
15
+ expect(subject.is_strong?('password')).to be_falsey
16
16
  end
17
17
  end
18
-
19
- describe '#is_weak?' do
20
- let(:subject) { QwertyAdjuster.new('password') }
21
18
 
19
+ describe '#is_weak?' do
22
20
  it 'returns the opposite of is_strong?' do
23
- subject.stub(is_strong?: true)
24
- expect(subject.is_weak?).to be_false
21
+ allow(subject).to receive_messages(is_strong?: true)
22
+ expect(subject.is_weak?('password')).to be_falsey
25
23
  end
26
24
  end
27
-
25
+
28
26
  describe '#adjusted_entropy' do
29
- before(:each) { NistBonusBits.stub(bonus_bits: 0)}
27
+ before(:each) { allow(NistBonusBits).to receive_messages(bonus_bits: 0) }
30
28
  {
31
29
  'qwertyuio' => 5.5,
32
30
  '1234567' => 6,
@@ -37,9 +35,21 @@ module StrongPassword
37
35
  'password' => 17.5 # Ensure that we don't qwerty-adjust 'password'
38
36
  }.each do |password, bits|
39
37
  it "returns #{bits} for '#{password}'" do
40
- expect(QwertyAdjuster.new(password).adjusted_entropy).to eq(bits)
38
+ expect(subject.adjusted_entropy(password)).to eq(bits)
39
+ end
40
+ end
41
+
42
+ describe 'with a default entropy threshhold' do
43
+ subject(:qwerty_adjuster) { QwertyAdjuster.new }
44
+
45
+ it 'returns the higher entropy before running qwerty adjustments' do
46
+ # Default threshhold is equal to the default min_entropy for a strong password (18).
47
+ # When not set we should get the base password's entropy from this (16) instead of the
48
+ # lower qwerty-adjusted entropy (6) indicating we avoided doing additional work in the
49
+ # qwerty adjustment code since we already know the password is weak.
50
+ expect(subject.adjusted_entropy('1234567')).to eq(16)
41
51
  end
42
52
  end
43
53
  end
44
54
  end
45
- end
55
+ end
@@ -11,11 +11,11 @@ module StrongPassword
11
11
  'aB$1' => false
12
12
  }.each do |password, strength|
13
13
  it "is_strong? returns #{strength} for '#{password}' with 12 bits of entropy" do
14
- expect(StrengthChecker.new(password).is_strong?(min_entropy: 12)).to be(strength)
14
+ expect(StrengthChecker.new(min_entropy: 12).is_strong?(password)).to be(strength)
15
15
  end
16
16
  end
17
17
  end
18
-
18
+
19
19
  context 'with lowered entropy requirement and dictionary checking' do
20
20
  {
21
21
  'blahblah' => true,
@@ -26,11 +26,11 @@ module StrongPassword
26
26
  'aB$1' => false
27
27
  }.each do |password, strength|
28
28
  it "is_strong? returns #{strength} for '#{password}' with 12 bits of entropy" do
29
- expect(StrengthChecker.new(password).is_strong?(min_entropy: 12, use_dictionary: true)).to eq(strength)
29
+ expect(StrengthChecker.new(min_entropy: 12, use_dictionary: true).is_strong?(password)).to eq(strength)
30
30
  end
31
31
  end
32
32
  end
33
-
33
+
34
34
  context 'with standard entropy requirement and dictionary checking' do
35
35
  {
36
36
  'blahblah' => false,
@@ -41,11 +41,11 @@ module StrongPassword
41
41
  'correct horse battery staple' => true
42
42
  }.each do |password, strength|
43
43
  it "is_strong? returns #{strength} for '#{password}' with standard bits of entropy" do
44
- expect(StrengthChecker.new(password).is_strong?(use_dictionary: true)).to eq(strength)
44
+ expect(StrengthChecker.new(use_dictionary: true).is_strong?(password)).to eq(strength)
45
45
  end
46
46
  end
47
47
  end
48
-
48
+
49
49
  context 'with crazy entropy requirement and dictionary checking' do
50
50
  {
51
51
  'blahblah' => false,
@@ -57,9 +57,32 @@ module StrongPassword
57
57
  'c0rr#ct h0rs3 Batt$ry st@pl3 is Gr34t' => true
58
58
  }.each do |password, strength|
59
59
  it "is_strong? returns #{strength} for '#{password}' with standard bits of entropy" do
60
- expect(StrengthChecker.new(password).is_strong?(min_entropy: 40, use_dictionary: true)).to eq(strength)
60
+ expect(StrengthChecker.new(min_entropy: 40, use_dictionary: true).is_strong?(password)).to eq(strength)
61
61
  end
62
62
  end
63
63
  end
64
+
65
+ context 'with long password' do
66
+ let(:strength_checker) { StrengthChecker.new }
67
+ let(:password) { ("ba"*500_000) }
68
+ it 'should be truncated' do
69
+ expect(strength_checker.calculate_entropy(password)).
70
+ to eq(strength_checker.calculate_entropy(password.slice(0, StrengthChecker::PASSWORD_LIMIT)))
71
+ end
72
+ end
73
+
74
+ context 'with long extra words' do
75
+ let(:strength_checker) { StrengthChecker.new(use_dictionary: true, extra_dictionary_words: ["a"*1_000_000, "b"*10_000_000, "c"*10]) }
76
+ let(:exta_limit) { StrengthChecker::EXTRA_WORDS_LIMIT }
77
+ it 'should be truncated' do
78
+ expect(DictionaryAdjuster).to receive(:new).with({
79
+ min_entropy: 18,
80
+ min_word_length: 4,
81
+ extra_dictionary_words:
82
+ ["a"*StrengthChecker::EXTRA_WORDS_LIMIT, "b"*StrengthChecker::EXTRA_WORDS_LIMIT, "c"*10]
83
+ }).and_call_original
84
+ strength_checker.calculate_entropy("$tr0NgP4s$w0rd91d£")
85
+ end
86
+ end
64
87
  end
65
- end
88
+ end
@@ -18,7 +18,7 @@ class TestStrengthStrongEntropy < User
18
18
  end
19
19
 
20
20
  class TestStrengthExtraWords < User
21
- validates :password, password_strength: {extra_dictionary_words: ['mcmanus'], use_dictionary: true}
21
+ validates :password, password_strength: {extra_dictionary_words: ['administrator'], use_dictionary: true}
22
22
  end
23
23
 
24
24
  class TestBaseStrengthAlternative < User
@@ -47,7 +47,7 @@ module ActiveModel
47
47
  it "adds errors when password is '#{password}'" do
48
48
  base_strength.password = password
49
49
  base_strength.valid?
50
- expect(base_strength.errors[:password]).to eq(["Password is too weak"])
50
+ expect(base_strength.errors[:password]).to eq(["is too weak"])
51
51
  end
52
52
  end
53
53
  end
@@ -79,7 +79,7 @@ module ActiveModel
79
79
  it "adds errors when password is '#{password}'" do
80
80
  alternative_usage.password = password
81
81
  alternative_usage.valid?
82
- expect(alternative_usage.errors[:password]).to eq(["Password is too weak"])
82
+ expect(alternative_usage.errors[:password]).to eq(["is too weak"])
83
83
  end
84
84
  end
85
85
  end
@@ -129,7 +129,7 @@ module ActiveModel
129
129
  it "'#{password}' should be invalid with increased entropy requirement" do
130
130
  strong_entropy.password = password
131
131
  strong_entropy.valid?
132
- expect(strong_entropy.errors[:password]).to eq(["Password is too weak"])
132
+ expect(strong_entropy.errors[:password]).to eq(["is too weak"])
133
133
  end
134
134
  end
135
135
  end
@@ -138,14 +138,18 @@ module ActiveModel
138
138
 
139
139
  describe 'extra words' do
140
140
  it 'allows extra words to be specified as an option to the validation' do
141
- password = 'mcmanus'
141
+ password = 'administratorWEQ@123'
142
+ # Validate that without 'administrator' added to extra_dictionary_words
143
+ # this password is considered strong
142
144
  weak_entropy.password = password
143
- expect(weak_entropy.valid?).to be_true
145
+ expect(weak_entropy.valid?).to be_truthy
146
+ # Now check that with 'administrator' added to extra_dictionary_words
147
+ # in our model, the same password is considered weak.
144
148
  extra_words.password = password
145
- expect(extra_words.valid?).to be_false
149
+ expect(extra_words.valid?).to be_falsey
146
150
  end
147
151
  end
148
152
  end
149
153
  end
150
154
  end
151
- end
155
+ end
@@ -18,7 +18,8 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.add_development_dependency 'bundler', '~> 1.3'
21
+ spec.add_development_dependency 'bundler', '>= 1.3'
22
22
  spec.add_development_dependency 'rake'
23
- spec.add_development_dependency 'rspec', '~> 2.12'
23
+ spec.add_development_dependency 'rspec', '~> 3.8'
24
+ spec.add_development_dependency 'pry'
24
25
  end
metadata CHANGED
@@ -1,57 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: strong_password
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian McManus
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-17 00:00:00.000000000 Z
11
+ date: 2021-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.3'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '2.12'
47
+ version: '3.8'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '2.12'
54
+ version: '3.8'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  description: Entropy-based password strength checking for Ruby and ActiveModel
56
70
  email:
57
71
  - bdmac97@gmail.com
@@ -59,7 +73,8 @@ executables: []
59
73
  extensions: []
60
74
  extra_rdoc_files: []
61
75
  files:
62
- - .gitignore
76
+ - ".gitignore"
77
+ - ".travis.yml"
63
78
  - CHANGELOG
64
79
  - Gemfile
65
80
  - LICENSE.txt
@@ -95,17 +110,16 @@ require_paths:
95
110
  - lib
96
111
  required_ruby_version: !ruby/object:Gem::Requirement
97
112
  requirements:
98
- - - '>='
113
+ - - ">="
99
114
  - !ruby/object:Gem::Version
100
115
  version: '0'
101
116
  required_rubygems_version: !ruby/object:Gem::Requirement
102
117
  requirements:
103
- - - '>='
118
+ - - ">="
104
119
  - !ruby/object:Gem::Version
105
120
  version: '0'
106
121
  requirements: []
107
- rubyforge_project:
108
- rubygems_version: 2.2.0
122
+ rubygems_version: 3.1.2
109
123
  signing_key:
110
124
  specification_version: 4
111
125
  summary: StrongPassword adds a class to check password strength and a validator for