zxcvbn-ruby 0.0.3 → 1.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.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +12 -0
  3. data/CHANGELOG.md +42 -0
  4. data/CODE_OF_CONDUCT.md +130 -0
  5. data/Gemfile +8 -1
  6. data/Guardfile +26 -0
  7. data/{LICENSE → LICENSE.txt} +0 -0
  8. data/README.md +165 -9
  9. data/Rakefile +5 -1
  10. data/lib/zxcvbn.rb +10 -36
  11. data/lib/zxcvbn/crack_time.rb +44 -42
  12. data/lib/zxcvbn/data.rb +29 -0
  13. data/lib/zxcvbn/dictionary_ranker.rb +0 -2
  14. data/lib/zxcvbn/entropy.rb +3 -1
  15. data/lib/zxcvbn/feedback.rb +10 -0
  16. data/lib/zxcvbn/feedback_giver.rb +133 -0
  17. data/lib/zxcvbn/matchers/date.rb +2 -0
  18. data/lib/zxcvbn/matchers/dictionary.rb +2 -0
  19. data/lib/zxcvbn/matchers/digits.rb +2 -0
  20. data/lib/zxcvbn/matchers/l33t.rb +2 -2
  21. data/lib/zxcvbn/matchers/regex_helpers.rb +2 -0
  22. data/lib/zxcvbn/matchers/repeat.rb +2 -0
  23. data/lib/zxcvbn/matchers/sequences.rb +2 -0
  24. data/lib/zxcvbn/matchers/spatial.rb +2 -0
  25. data/lib/zxcvbn/matchers/year.rb +2 -0
  26. data/lib/zxcvbn/math.rb +2 -2
  27. data/lib/zxcvbn/omnimatch.rb +14 -3
  28. data/lib/zxcvbn/password_strength.rb +7 -3
  29. data/lib/zxcvbn/score.rb +1 -1
  30. data/lib/zxcvbn/scorer.rb +11 -0
  31. data/lib/zxcvbn/tester.rb +43 -0
  32. data/lib/zxcvbn/version.rb +1 -1
  33. data/spec/dictionary_ranker_spec.rb +2 -2
  34. data/spec/feedback_giver_spec.rb +212 -0
  35. data/spec/matchers/date_spec.rb +8 -8
  36. data/spec/matchers/dictionary_spec.rb +25 -14
  37. data/spec/matchers/digits_spec.rb +3 -3
  38. data/spec/matchers/l33t_spec.rb +15 -13
  39. data/spec/matchers/repeat_spec.rb +6 -6
  40. data/spec/matchers/sequences_spec.rb +5 -5
  41. data/spec/matchers/spatial_spec.rb +8 -8
  42. data/spec/matchers/year_spec.rb +3 -3
  43. data/spec/omnimatch_spec.rb +2 -2
  44. data/spec/scoring/crack_time_spec.rb +13 -13
  45. data/spec/scoring/entropy_spec.rb +28 -25
  46. data/spec/scoring/math_spec.rb +22 -18
  47. data/spec/support/matcher.rb +1 -1
  48. data/spec/tester_spec.rb +99 -0
  49. data/spec/zxcvbn_spec.rb +14 -39
  50. data/zxcvbn-ruby.gemspec +11 -0
  51. metadata +34 -29
@@ -17,7 +17,7 @@ RSpec::Matchers.define :match_js_results do |expected_js_results|
17
17
  @missing.empty? && @extra.empty?
18
18
  end
19
19
 
20
- failure_message_for_should do |actual|
20
+ failure_message do |actual|
21
21
  "Matches missing from ruby results:\n#{@missing.inspect}\nMatches unique to ruby results:\n#{@extra.inspect}"
22
22
  end
23
23
 
@@ -0,0 +1,99 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ require "spec_helper"
5
+
6
+ describe Zxcvbn::Tester do
7
+ let(:tester) { Zxcvbn::Tester.new }
8
+
9
+ TEST_PASSWORDS.each do |password|
10
+ it "gives back the same score for #{password}" do
11
+ ruby_result = tester.test(password)
12
+ js_result = js_zxcvbn(password)
13
+
14
+ expect(ruby_result.calc_time).not_to be_nil
15
+ expect(ruby_result.password).to eq js_result["password"]
16
+ expect(ruby_result.entropy).to eq js_result["entropy"]
17
+ expect(ruby_result.crack_time).to eq js_result["crack_time"]
18
+ expect(ruby_result.crack_time_display).to eq js_result["crack_time_display"]
19
+ expect(ruby_result.score).to eq js_result["score"]
20
+ expect(ruby_result.pattern).to eq js_result["pattern"]
21
+ expect(ruby_result.match_sequence.count).to eq js_result["match_sequence"].count
22
+
23
+ # NOTE: feedback didn't exist in the version of the JS library this gem
24
+ # is based on, so instead we just check that it put `Feedback` in
25
+ # there. Real tests for its values go in `feedback_giver_spec.rb`.
26
+ expect(ruby_result.feedback).to be_a Zxcvbn::Feedback
27
+ end
28
+ end
29
+
30
+ context "with a custom user dictionary" do
31
+ it "scores them against the user dictionary" do
32
+ result = tester.test("themeforest", ["themeforest"])
33
+ expect(result.entropy).to eq 0
34
+ expect(result.score).to eq 0
35
+ end
36
+
37
+ it "matches l33t substitutions on this dictionary" do
38
+ result = tester.test("th3m3for3st", ["themeforest"])
39
+ expect(result.entropy).to eq 1
40
+ expect(result.score).to eq 0
41
+ end
42
+ end
43
+
44
+ context "with Unicode entries in the password" do
45
+ it "validates the password" do
46
+ result = tester.test("✅🐴🔋staple", %w[Theme Forest themeforest])
47
+ expect(result.entropy).to be_positive
48
+ expect(result.score).to be_positive
49
+ end
50
+ end
51
+
52
+ context "with Unicode entries in the dictionary" do
53
+ it "validates the password" do
54
+ result = tester.test("correct horse battery staple", %w[✅ 🐴 🔋])
55
+ expect(result.entropy).to be_positive
56
+ expect(result.score).to be_positive
57
+ end
58
+ end
59
+
60
+ context "with Unicode entries in the password and the dictionary" do
61
+ it "validates the password" do
62
+ result = tester.test("✅🐴🔋staple", %w[✅ 🐴 🔋])
63
+ expect(result.entropy).to be_positive
64
+ expect(result.score).to be_zero
65
+ end
66
+ end
67
+
68
+ context "with invalid entries in the dictionary" do
69
+ it "ignores those entries" do
70
+ result = tester.test("themeforest", [nil, 1, "themeforest"])
71
+ expect(result.entropy).to eq 0
72
+ expect(result.score).to eq 0
73
+ end
74
+ end
75
+
76
+ context "with a custom global dictionary" do
77
+ before { tester.add_word_lists("envato" => ["envato"]) }
78
+
79
+ it "scores them against the dictionary" do
80
+ result = tester.test("envato")
81
+ expect(result.entropy).to eq 0
82
+ expect(result.score).to eq 0
83
+ end
84
+
85
+ context "with invalid entries in a custom dictionary" do
86
+ before { tester.add_word_lists("themeforest" => [nil, 1, "themeforest"]) }
87
+
88
+ it "ignores those entries" do
89
+ expect(tester.test("themeforest")).to have_attributes(entropy: 0, score: 0, crack_time: 0)
90
+ end
91
+ end
92
+ end
93
+
94
+ context "nil password" do
95
+ specify do
96
+ expect(tester.test(nil)).to have_attributes(entropy: 0, score: 0, crack_time: 0)
97
+ end
98
+ end
99
+ end
@@ -1,49 +1,24 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'zxcvbn over a set of example passwords' do
4
- TEST_PASSWORDS.each do |password|
5
- it "gives back the same score for #{password}" do
6
- ruby_result = Zxcvbn.test(password)
7
- js_result = js_zxcvbn(password)
8
-
9
- ruby_result.calc_time.should_not be_nil
10
- ruby_result.password.should eq js_result['password']
11
- ruby_result.entropy.should eq js_result['entropy']
12
- ruby_result.crack_time.should eq js_result['crack_time']
13
- ruby_result.crack_time_display.should eq js_result['crack_time_display']
14
- ruby_result.score.should eq js_result['score']
15
- ruby_result.pattern.should eq js_result['pattern']
16
- ruby_result.match_sequence.count.should eq js_result['match_sequence'].count
3
+ describe 'Zxcvbn.test' do
4
+ context 'with a password' do
5
+ it 'returns a result' do
6
+ result = Zxcvbn.test('password')
7
+ expect(result.entropy).to_not be_nil
17
8
  end
18
9
  end
19
10
 
20
- context 'with a custom user dictionary' do
21
- it 'scores them against the user dictionary' do
22
- result = Zxcvbn.test('themeforest', ['themeforest'])
23
- result.entropy.should eq 0
24
- result.score.should eq 0
25
- end
26
-
27
- it 'matches l33t substitutions on this dictionary' do
28
- result = Zxcvbn.test('th3m3for3st', ['themeforest'])
29
- result.entropy.should eq 1
30
- result.score.should eq 0
31
- end
32
- end
33
-
34
- context 'with a custom global dictionary' do
35
- before { Zxcvbn.add_word_list('envato', ['envato']) }
36
-
37
- it 'scores them against the dictionary' do
38
- result = Zxcvbn.test('envato')
39
- result.entropy.should eq 0
40
- result.score.should eq 0
11
+ context 'with a password and user input' do
12
+ it 'returns a result' do
13
+ result = Zxcvbn.test('password', ['inputs'])
14
+ expect(result.entropy).to_not be_nil
41
15
  end
42
16
  end
43
17
 
44
- context 'nil password' do
45
- specify do
46
- expect { Zxcvbn.test(nil) }.to_not raise_error
18
+ context 'with a password, user input and custom word lists' do
19
+ it 'returns a result' do
20
+ result = Zxcvbn.test('password', ['inputs'], {'list' => ['words']})
21
+ expect(result.entropy).to_not be_nil
47
22
  end
48
23
  end
49
- end
24
+ end
@@ -14,7 +14,18 @@ Gem::Specification.new do |gem|
14
14
  gem.name = "zxcvbn-ruby"
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = Zxcvbn::VERSION
17
+ gem.license = 'MIT'
18
+
19
+ gem.required_ruby_version = '~> 2.5'
17
20
 
18
21
  gem.add_development_dependency 'therubyracer'
19
22
  gem.add_development_dependency 'rspec'
23
+
24
+ gem.metadata = {
25
+ "bug_tracker_uri" => "https://github.com/envato/zxcvbn-ruby/issues",
26
+ "changelog_uri" => "https://github.com/envato/zxcvbn-ruby/blob/master/CHANGELOG.md",
27
+ "documentation_uri" => "https://github.com/envato/zxcvbn-ruby/blob/master/README.md",
28
+ "homepage_uri" => "https://github.com/envato/zxcvbn-ruby",
29
+ "source_code_uri" => "https://github.com/envato/zxcvbn-ruby"
30
+ }
20
31
  end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zxcvbn-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
5
- prerelease:
4
+ version: 1.1.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Steve Hodgkiss
@@ -10,38 +9,34 @@ authors:
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2015-02-19 00:00:00.000000000 Z
12
+ date: 2020-07-15 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: therubyracer
17
16
  requirement: !ruby/object:Gem::Requirement
18
- none: false
19
17
  requirements:
20
- - - ! '>='
18
+ - - ">="
21
19
  - !ruby/object:Gem::Version
22
20
  version: '0'
23
21
  type: :development
24
22
  prerelease: false
25
23
  version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
24
  requirements:
28
- - - ! '>='
25
+ - - ">="
29
26
  - !ruby/object:Gem::Version
30
27
  version: '0'
31
28
  - !ruby/object:Gem::Dependency
32
29
  name: rspec
33
30
  requirement: !ruby/object:Gem::Requirement
34
- none: false
35
31
  requirements:
36
- - - ! '>='
32
+ - - ">="
37
33
  - !ruby/object:Gem::Version
38
34
  version: '0'
39
35
  type: :development
40
36
  prerelease: false
41
37
  version_requirements: !ruby/object:Gem::Requirement
42
- none: false
43
38
  requirements:
44
- - - ! '>='
39
+ - - ">="
45
40
  - !ruby/object:Gem::Version
46
41
  version: '0'
47
42
  description: Ruby port of Dropboxs zxcvbn.js
@@ -52,10 +47,14 @@ executables: []
52
47
  extensions: []
53
48
  extra_rdoc_files: []
54
49
  files:
55
- - .gitignore
56
- - .rspec
50
+ - ".gitignore"
51
+ - ".rspec"
52
+ - ".travis.yml"
53
+ - CHANGELOG.md
54
+ - CODE_OF_CONDUCT.md
57
55
  - Gemfile
58
- - LICENSE
56
+ - Guardfile
57
+ - LICENSE.txt
59
58
  - README.md
60
59
  - Rakefile
61
60
  - data/adjacency_graphs.json
@@ -66,8 +65,11 @@ files:
66
65
  - data/frequency_lists/surnames.txt
67
66
  - lib/zxcvbn.rb
68
67
  - lib/zxcvbn/crack_time.rb
68
+ - lib/zxcvbn/data.rb
69
69
  - lib/zxcvbn/dictionary_ranker.rb
70
70
  - lib/zxcvbn/entropy.rb
71
+ - lib/zxcvbn/feedback.rb
72
+ - lib/zxcvbn/feedback_giver.rb
71
73
  - lib/zxcvbn/match.rb
72
74
  - lib/zxcvbn/matchers/date.rb
73
75
  - lib/zxcvbn/matchers/dictionary.rb
@@ -84,8 +86,10 @@ files:
84
86
  - lib/zxcvbn/password_strength.rb
85
87
  - lib/zxcvbn/score.rb
86
88
  - lib/zxcvbn/scorer.rb
89
+ - lib/zxcvbn/tester.rb
87
90
  - lib/zxcvbn/version.rb
88
91
  - spec/dictionary_ranker_spec.rb
92
+ - spec/feedback_giver_spec.rb
89
93
  - spec/matchers/date_spec.rb
90
94
  - spec/matchers/dictionary_spec.rb
91
95
  - spec/matchers/digits_spec.rb
@@ -111,40 +115,40 @@ files:
111
115
  - spec/support/js_source/scoring.coffee
112
116
  - spec/support/js_source/scoring.js
113
117
  - spec/support/matcher.rb
118
+ - spec/tester_spec.rb
114
119
  - spec/zxcvbn_spec.rb
115
120
  - zxcvbn-ruby.gemspec
116
121
  homepage: http://github.com/envato/zxcvbn-ruby
117
- licenses: []
122
+ licenses:
123
+ - MIT
124
+ metadata:
125
+ bug_tracker_uri: https://github.com/envato/zxcvbn-ruby/issues
126
+ changelog_uri: https://github.com/envato/zxcvbn-ruby/blob/master/CHANGELOG.md
127
+ documentation_uri: https://github.com/envato/zxcvbn-ruby/blob/master/README.md
128
+ homepage_uri: https://github.com/envato/zxcvbn-ruby
129
+ source_code_uri: https://github.com/envato/zxcvbn-ruby
118
130
  post_install_message:
119
131
  rdoc_options: []
120
132
  require_paths:
121
133
  - lib
122
134
  required_ruby_version: !ruby/object:Gem::Requirement
123
- none: false
124
135
  requirements:
125
- - - ! '>='
136
+ - - "~>"
126
137
  - !ruby/object:Gem::Version
127
- version: '0'
128
- segments:
129
- - 0
130
- hash: -1798543645320205772
138
+ version: '2.5'
131
139
  required_rubygems_version: !ruby/object:Gem::Requirement
132
- none: false
133
140
  requirements:
134
- - - ! '>='
141
+ - - ">="
135
142
  - !ruby/object:Gem::Version
136
143
  version: '0'
137
- segments:
138
- - 0
139
- hash: -1798543645320205772
140
144
  requirements: []
141
- rubyforge_project:
142
- rubygems_version: 1.8.23.2
145
+ rubygems_version: 3.1.2
143
146
  signing_key:
144
- specification_version: 3
147
+ specification_version: 4
145
148
  summary: ''
146
149
  test_files:
147
150
  - spec/dictionary_ranker_spec.rb
151
+ - spec/feedback_giver_spec.rb
148
152
  - spec/matchers/date_spec.rb
149
153
  - spec/matchers/dictionary_spec.rb
150
154
  - spec/matchers/digits_spec.rb
@@ -170,4 +174,5 @@ test_files:
170
174
  - spec/support/js_source/scoring.coffee
171
175
  - spec/support/js_source/scoring.js
172
176
  - spec/support/matcher.rb
177
+ - spec/tester_spec.rb
173
178
  - spec/zxcvbn_spec.rb