nobspw 0.4.0 → 0.6.2
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +3 -3
- data/README.md +4 -3
- data/lib/active_model/validations/password_validator.rb +1 -0
- data/lib/nobspw/configuration.rb +2 -0
- data/lib/nobspw/password_checker.rb +2 -5
- data/lib/nobspw/validation_methods.rb +42 -13
- data/lib/nobspw/version.rb +1 -1
- data/misc/grep_benchmark.rb +73 -0
- data/nobspw.gemspec +4 -2
- metadata +38 -10
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: d81c15016a1b06dc3d38fc995120b526574a65cd5fd13ed98bc05e614f189b5b
         | 
| 4 | 
            +
              data.tar.gz: a7303590e8fa254ad9718fda4444a2c3d5faabb77cc528d5a5284e52792742be
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 2e8b250a5a326593bab9f576cdc7ec15da4e03573c273bacc62b74f46c4977df5e323b079aa43f613d17f458f1417b1f569e2f7dd19f190be16af5b0b68e7a13
         | 
| 7 | 
            +
              data.tar.gz: 6ab6462e6c32b58a1f79cd01ffa0a540fab446f22db43b43c52366821a3a185f7c5a1c5b78cd938f4a5be94c2f93ba1cc094f9a456c8d957c68cfa079c7a2cba
         | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/.travis.yml
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -60,8 +60,9 @@ Optionally, you can configure some options: | |
| 60 60 | 
             
                config.min_unique_characters = 5
         | 
| 61 61 | 
             
                config.dictionary_path = 'path/to/dictionary.txt'
         | 
| 62 62 | 
             
                config.grep_path = '/usr/bin/grep'
         | 
| 63 | 
            +
                config.use_ruby_grep = false # Defaults to false; slower when true. Uses Ruby's internal Grep method instead of shelling out.
         | 
| 63 64 | 
             
                config.domain_name = 'mywebsitedomain.com' # it is recommended you configure this
         | 
| 64 | 
            -
                config.blacklist = ['this_password_is_not_allowed']
         | 
| 65 | 
            +
                config.blacklist = ['this_password_is_not_allowed', /password/]
         | 
| 65 66 | 
             
              end
         | 
| 66 67 | 
             
            ```
         | 
| 67 68 |  | 
| @@ -70,7 +71,7 @@ Optionally, you can configure some options: | |
| 70 71 | 
             
            I included `PasswordValidator` for Rails. Validating passwords in your model couldn't be easier:
         | 
| 71 72 |  | 
| 72 73 | 
             
            ```ruby
         | 
| 73 | 
            -
            validates :password, presence: true, password: true, if: -> { new_record? || changes[:password] }
         | 
| 74 | 
            +
            validates :password, presence: true, password: true, if: -> { new_record? || changes[:password] || changes[:password_digest] }
         | 
| 74 75 | 
             
            ```
         | 
| 75 76 |  | 
| 76 77 | 
             
            PasswordValidator will try to guess the correct field name for each `PasswordChecker` argument as follow:
         | 
| @@ -84,7 +85,7 @@ If you have field names different than above, you can tell `PasswordValidator` w | |
| 84 85 | 
             
            ```ruby
         | 
| 85 86 | 
             
            validates :password, password: { :name => :customer_name,
         | 
| 86 87 | 
             
                                             :email => :electronic_address },
         | 
| 87 | 
            -
                      if: -> { new_record? || changes[:password] }
         | 
| 88 | 
            +
                      if: -> { new_record? || changes[:password] || changes[:password_digest] }
         | 
| 88 89 | 
             
            ```
         | 
| 89 90 |  | 
| 90 91 | 
             
            ## Validations
         | 
| @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            class ActiveModel::Validations::PasswordValidator < ActiveModel::EachValidator
         | 
| 2 2 | 
             
              DEFAULT_ERROR_MESSAGES = {
         | 
| 3 3 | 
             
                name_included_in_password: 'is too similar to your name',
         | 
| 4 | 
            +
                username_included_in_password: 'is too similar to your username',
         | 
| 4 5 | 
             
                email_included_in_password: 'is too similar to your email',
         | 
| 5 6 | 
             
                domain_included_in_password: 'is too similar to this domain name',
         | 
| 6 7 | 
             
                password_too_short: 'is too short',
         | 
    
        data/lib/nobspw/configuration.rb
    CHANGED
    
    | @@ -5,6 +5,7 @@ module NOBSPW | |
| 5 5 | 
             
                attr_accessor :min_unique_characters
         | 
| 6 6 | 
             
                attr_accessor :dictionary_path
         | 
| 7 7 | 
             
                attr_accessor :grep_path
         | 
| 8 | 
            +
                attr_accessor :use_ruby_grep
         | 
| 8 9 | 
             
                attr_accessor :domain_name
         | 
| 9 10 | 
             
                attr_accessor :blacklist
         | 
| 10 11 | 
             
                attr_accessor :validation_methods
         | 
| @@ -16,6 +17,7 @@ module NOBSPW | |
| 16 17 | 
             
                  @min_unique_characters    = 5
         | 
| 17 18 | 
             
                  @dictionary_path          = File.join(File.dirname(__FILE__), "..", "db", "dictionary.txt")
         | 
| 18 19 | 
             
                  @grep_path                = `which grep`.strip
         | 
| 20 | 
            +
                  @use_ruby_grep            = @grep_path.empty?
         | 
| 19 21 | 
             
                  @domain_name              = nil
         | 
| 20 22 | 
             
                  @blacklist                = nil
         | 
| 21 23 | 
             
                  @validation_methods       = NOBSPW::ValidationMethods::DEFAULT_VALIDATION_METHODS
         | 
| @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            require 'shellwords'
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            module NOBSPW
         | 
| 2 4 | 
             
              class PasswordChecker
         | 
| 3 5 | 
             
                include NOBSPW::ValidationMethods
         | 
| @@ -26,7 +28,6 @@ module NOBSPW | |
| 26 28 |  | 
| 27 29 | 
             
                def check_password
         | 
| 28 30 | 
             
                  @weak_password_reasons = []
         | 
| 29 | 
            -
             | 
| 30 31 | 
             
                  NOBSPW.configuration.validation_methods.each do |method|
         | 
| 31 32 | 
             
                    if send("#{method}")
         | 
| 32 33 | 
             
                      @weak_password_reasons << method.to_s.sub(/\?$/, '').to_sym
         | 
| @@ -36,9 +37,5 @@ module NOBSPW | |
| 36 37 |  | 
| 37 38 | 
             
                  @strong = @weak_password_reasons.empty?
         | 
| 38 39 | 
             
                end
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                def grep_command(path)
         | 
| 41 | 
            -
                  "#{NOBSPW.configuration.grep_path} '^#{@password}$' #{path}"
         | 
| 42 | 
            -
                end
         | 
| 43 40 | 
             
              end
         | 
| 44 41 | 
             
            end
         | 
| @@ -1,7 +1,11 @@ | |
| 1 | 
            +
            require 'shellwords'
         | 
| 2 | 
            +
            require 'open3'
         | 
| 3 | 
            +
             | 
| 1 4 | 
             
            module NOBSPW
         | 
| 2 5 | 
             
              module ValidationMethods
         | 
| 3 6 | 
             
                DEFAULT_VALIDATION_METHODS = %i(password_empty?
         | 
| 4 7 | 
             
                                                name_included_in_password?
         | 
| 8 | 
            +
                                                username_included_in_password?
         | 
| 5 9 | 
             
                                                email_included_in_password?
         | 
| 6 10 | 
             
                                                domain_included_in_password?
         | 
| 7 11 | 
             
                                                password_too_short?
         | 
| @@ -11,6 +15,8 @@ module NOBSPW | |
| 11 15 | 
             
                                                password_too_common?)
         | 
| 12 16 |  | 
| 13 17 | 
             
                INTERRUPT_VALIDATION_FOR   = %i(password_empty?)
         | 
| 18 | 
            +
                STDIN_GREP_COMMAND         = ['/usr/bin/grep', '-m 1', '-f', '/dev/stdin',
         | 
| 19 | 
            +
                                              NOBSPW.configuration.dictionary_path]
         | 
| 14 20 |  | 
| 15 21 | 
             
                private
         | 
| 16 22 |  | 
| @@ -24,6 +30,12 @@ module NOBSPW | |
| 24 30 | 
             
                  words_included_in_password?(words)
         | 
| 25 31 | 
             
                end
         | 
| 26 32 |  | 
| 33 | 
            +
                def username_included_in_password?
         | 
| 34 | 
            +
                  return nil unless @username
         | 
| 35 | 
            +
                  words = remove_word_separators(@username).split(' ')
         | 
| 36 | 
            +
                  words_included_in_password?(words)
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 27 39 | 
             
                def email_included_in_password?
         | 
| 28 40 | 
             
                  return nil unless @email
         | 
| 29 41 | 
             
                  words = remove_word_separators(email_without_extension(@email)).split(' ')
         | 
| @@ -40,7 +52,16 @@ module NOBSPW | |
| 40 52 |  | 
| 41 53 | 
             
                def password_not_allowed?
         | 
| 42 54 | 
             
                  return nil unless NOBSPW.configuration.blacklist
         | 
| 43 | 
            -
             | 
| 55 | 
            +
             | 
| 56 | 
            +
                  NOBSPW.configuration.blacklist.each do |expression|
         | 
| 57 | 
            +
                    if expression.is_a?(Regexp)
         | 
| 58 | 
            +
                      return true if @password.match?(expression)
         | 
| 59 | 
            +
                    else
         | 
| 60 | 
            +
                      return true if expression.to_s == @password
         | 
| 61 | 
            +
                    end
         | 
| 62 | 
            +
                  end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                  false
         | 
| 44 65 | 
             
                end
         | 
| 45 66 |  | 
| 46 67 | 
             
                def password_too_short?
         | 
| @@ -65,22 +86,27 @@ module NOBSPW | |
| 65 86 | 
             
                end
         | 
| 66 87 |  | 
| 67 88 | 
             
                def password_too_common?
         | 
| 68 | 
            -
                   | 
| 69 | 
            -
             | 
| 70 | 
            -
                  case $?.exitstatus
         | 
| 71 | 
            -
                  when 0
         | 
| 72 | 
            -
                    true
         | 
| 73 | 
            -
                  when 1
         | 
| 74 | 
            -
                    false
         | 
| 75 | 
            -
                  when 127
         | 
| 76 | 
            -
                    raise StandardError.new("Grep not found at: #{NOBSPW.configuration.grep_path}")
         | 
| 77 | 
            -
                  else
         | 
| 78 | 
            -
                    false
         | 
| 79 | 
            -
                  end
         | 
| 89 | 
            +
                  NOBSPW.configuration.use_ruby_grep ? ruby_grep : shell_grep
         | 
| 80 90 | 
             
                end
         | 
| 81 91 |  | 
| 82 92 | 
             
                # Helper methods
         | 
| 83 93 |  | 
| 94 | 
            +
                def shell_grep
         | 
| 95 | 
            +
                  raise StandardError.new("Grep not found at: #{NOBSPW.configuration.grep_path}") \
         | 
| 96 | 
            +
                    if !File.exist?(NOBSPW.configuration.grep_path)
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                  output = Open3.popen3(STDIN_GREP_COMMAND.join(" "), out: '/dev/null') { |stdin, stdout, stderr, wait_thr|
         | 
| 99 | 
            +
                    stdin.puts "^#{escaped_password}$"
         | 
| 100 | 
            +
                    stdin.close
         | 
| 101 | 
            +
                    wait_thr.value
         | 
| 102 | 
            +
                  }
         | 
| 103 | 
            +
                  output.success?
         | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                def ruby_grep
         | 
| 107 | 
            +
                  File.open(NOBSPW.configuration.dictionary_path).grep(/^#{escaped_password}$/).any?
         | 
| 108 | 
            +
                end
         | 
| 109 | 
            +
             | 
| 84 110 | 
             
                def email_without_extension(email)
         | 
| 85 111 | 
             
                  name, domain, whatev = email&.split("@", 3)
         | 
| 86 112 | 
             
                  "#{name}@#{strip_extension_from_domain(domain)}"
         | 
| @@ -94,5 +120,8 @@ module NOBSPW | |
| 94 120 | 
             
                  str&.gsub(/-|_|\.|\'|\"|\@/, ' ')
         | 
| 95 121 | 
             
                end
         | 
| 96 122 |  | 
| 123 | 
            +
                def escaped_password(password = @password)
         | 
| 124 | 
            +
                  Shellwords.escape(password)
         | 
| 125 | 
            +
                end
         | 
| 97 126 | 
             
              end
         | 
| 98 127 | 
             
            end
         | 
    
        data/lib/nobspw/version.rb
    CHANGED
    
    
| @@ -0,0 +1,73 @@ | |
| 1 | 
            +
            #! /usr/bin/env ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'benchmark'
         | 
| 4 | 
            +
            require 'shellwords'
         | 
| 5 | 
            +
            require 'open3'
         | 
| 6 | 
            +
            require 'subprocess'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            ITERATIONS         = 100
         | 
| 9 | 
            +
            DICTIONARY_PATH    = File.join(File.dirname(__FILE__), '..', 'lib/db/dictionary.txt')
         | 
| 10 | 
            +
            STDIN_GREP_COMMAND = ['/usr/bin/grep', '-m 1', '-f', '/dev/stdin', DICTIONARY_PATH]
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            password = 'swordfish'
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            def shell_grep(password)
         | 
| 15 | 
            +
              password = Shellwords.escape(password)
         | 
| 16 | 
            +
              `/usr/bin/grep -m 1 '^#{password}$' #{DICTIONARY_PATH}`
         | 
| 17 | 
            +
              $?.exitstatus == 0
         | 
| 18 | 
            +
            end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            def shell_grep_open3(password)
         | 
| 21 | 
            +
              password = Shellwords.escape(password)
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              output = Open3.popen3(STDIN_GREP_COMMAND.join(" "), out: '/dev/null') { |stdin, stdout, stderr, wait_thr|
         | 
| 24 | 
            +
                stdin.puts "^#{password}$"
         | 
| 25 | 
            +
                stdin.close
         | 
| 26 | 
            +
                wait_thr.value
         | 
| 27 | 
            +
              }
         | 
| 28 | 
            +
              output.success?
         | 
| 29 | 
            +
            end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            def shell_grep_subprocess(password)
         | 
| 32 | 
            +
              password = Shellwords.escape(password)
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              Subprocess.check_call(STDIN_GREP_COMMAND, stdin: Subprocess::PIPE, stdout: '/dev/null') do |p|
         | 
| 35 | 
            +
                p.communicate("^#{password}$")
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
              true
         | 
| 38 | 
            +
            rescue Subprocess::NonZeroExit
         | 
| 39 | 
            +
              false
         | 
| 40 | 
            +
            end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            def ruby_grep(password)
         | 
| 43 | 
            +
              File.open(DICTIONARY_PATH).grep(/^#{password}$/)
         | 
| 44 | 
            +
            end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            def ruby_loop(password)
         | 
| 47 | 
            +
              File.open(DICTIONARY_PATH).read_line do |l|
         | 
| 48 | 
            +
                return true if l.match?(/^#{password}$/)
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
              false
         | 
| 51 | 
            +
            end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            Benchmark.bm(17) do |benchmark|
         | 
| 54 | 
            +
              benchmark.report("Shell") do
         | 
| 55 | 
            +
                ITERATIONS.times { shell_grep(password) }
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
              benchmark.report("Ruby Grep") do
         | 
| 59 | 
            +
                ITERATIONS.times { ruby_grep(password) }
         | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
              benchmark.report("Ruby Loop") do
         | 
| 63 | 
            +
                ITERATIONS.times { ruby_grep(password) }
         | 
| 64 | 
            +
              end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
              benchmark.report("Open3 stdin") do
         | 
| 67 | 
            +
                ITERATIONS.times { shell_grep_open3(password) }
         | 
| 68 | 
            +
              end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
              benchmark.report("Subprocess stdin") do
         | 
| 71 | 
            +
                ITERATIONS.times { shell_grep_subprocess(password) }
         | 
| 72 | 
            +
              end
         | 
| 73 | 
            +
            end
         | 
    
        data/nobspw.gemspec
    CHANGED
    
    | @@ -21,14 +21,16 @@ Gem::Specification.new do |spec| | |
| 21 21 | 
             
              spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
         | 
| 22 22 | 
             
              spec.require_paths = ["lib"]
         | 
| 23 23 |  | 
| 24 | 
            -
              spec.add_development_dependency "bundler" | 
| 25 | 
            -
              spec.add_development_dependency "rake", "~>  | 
| 24 | 
            +
              spec.add_development_dependency "bundler"
         | 
| 25 | 
            +
              spec.add_development_dependency "rake", "~> 12.3.3"
         | 
| 26 26 | 
             
              spec.add_development_dependency "rspec", "~> 3.0"
         | 
| 27 27 | 
             
              spec.add_development_dependency "simplecov", "~> 0.13"
         | 
| 28 28 | 
             
              spec.add_development_dependency "guard", "~> 2.14"
         | 
| 29 29 | 
             
              spec.add_development_dependency "guard-rspec", "~> 4.7.3"
         | 
| 30 30 | 
             
              spec.add_development_dependency "activemodel", "~> 5.0"
         | 
| 31 31 | 
             
              spec.add_development_dependency "i18n", "~> 0.8.1"
         | 
| 32 | 
            +
              spec.add_development_dependency "subprocess"
         | 
| 33 | 
            +
              spec.add_development_dependency "byebug"
         | 
| 32 34 |  | 
| 33 35 | 
             
              if RUBY_PLATFORM =~ /darwin/
         | 
| 34 36 | 
             
                spec.add_development_dependency 'ruby_gntp', "~> 0.3.4"
         | 
    
        metadata
    CHANGED
    
    | @@ -1,43 +1,43 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: nobspw
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.6.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Carl Mercier
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2020-06-29 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 | 
            -
                    version: ' | 
| 19 | 
            +
                    version: '0'
         | 
| 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 | 
            -
                    version: ' | 
| 26 | 
            +
                    version: '0'
         | 
| 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 | 
            -
                    version:  | 
| 33 | 
            +
                    version: 12.3.3
         | 
| 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 | 
            -
                    version:  | 
| 40 | 
            +
                    version: 12.3.3
         | 
| 41 41 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 42 42 | 
             
              name: rspec
         | 
| 43 43 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -122,6 +122,34 @@ dependencies: | |
| 122 122 | 
             
                - - "~>"
         | 
| 123 123 | 
             
                  - !ruby/object:Gem::Version
         | 
| 124 124 | 
             
                    version: 0.8.1
         | 
| 125 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 126 | 
            +
              name: subprocess
         | 
| 127 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 128 | 
            +
                requirements:
         | 
| 129 | 
            +
                - - ">="
         | 
| 130 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 131 | 
            +
                    version: '0'
         | 
| 132 | 
            +
              type: :development
         | 
| 133 | 
            +
              prerelease: false
         | 
| 134 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 135 | 
            +
                requirements:
         | 
| 136 | 
            +
                - - ">="
         | 
| 137 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 138 | 
            +
                    version: '0'
         | 
| 139 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 140 | 
            +
              name: byebug
         | 
| 141 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 142 | 
            +
                requirements:
         | 
| 143 | 
            +
                - - ">="
         | 
| 144 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 145 | 
            +
                    version: '0'
         | 
| 146 | 
            +
              type: :development
         | 
| 147 | 
            +
              prerelease: false
         | 
| 148 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 149 | 
            +
                requirements:
         | 
| 150 | 
            +
                - - ">="
         | 
| 151 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 152 | 
            +
                    version: '0'
         | 
| 125 153 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 126 154 | 
             
              name: ruby_gntp
         | 
| 127 155 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -175,6 +203,7 @@ files: | |
| 175 203 | 
             
            - lib/nobspw/password_checker.rb
         | 
| 176 204 | 
             
            - lib/nobspw/validation_methods.rb
         | 
| 177 205 | 
             
            - lib/nobspw/version.rb
         | 
| 206 | 
            +
            - misc/grep_benchmark.rb
         | 
| 178 207 | 
             
            - nobspw.gemspec
         | 
| 179 208 | 
             
            homepage: https://github.com/cmer/nobspw
         | 
| 180 209 | 
             
            licenses:
         | 
| @@ -195,8 +224,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 195 224 | 
             
                - !ruby/object:Gem::Version
         | 
| 196 225 | 
             
                  version: '0'
         | 
| 197 226 | 
             
            requirements: []
         | 
| 198 | 
            -
             | 
| 199 | 
            -
            rubygems_version: 2.7.3
         | 
| 227 | 
            +
            rubygems_version: 3.1.2
         | 
| 200 228 | 
             
            signing_key: 
         | 
| 201 229 | 
             
            specification_version: 4
         | 
| 202 230 | 
             
            summary: No Bullshit Password strength checker
         |