passrock 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 006903c5325cd4eabe082e5b18f7cd8dc6b0e1e6
4
+ data.tar.gz: c4febb93f9d06f5719d779fec992474bdb6e2f0f
5
+ SHA512:
6
+ metadata.gz: 25f6c1159dc62afade5a1f7a58e160884469f56bf0d77e363a838098317340d0c5f36dd67a222a05d1c4cf58905d383650d5e2d391c57a0dbe4878737059cb63
7
+ data.tar.gz: ecb64da91a081c048a4176b69ca9c9b7e344571bb87a45b5eefefec00fd8701f29232809e2e69001b2e128c46f77ac016c12142ea9383b1d4ae4bbbb0d6824bb
data/.env.example ADDED
@@ -0,0 +1,2 @@
1
+ PASSROCK_PASSWORD_DB=/path/to/passrock/testPRbinary.dat
2
+ PASSROCK_PRIVATE_KEY=xxx
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .env
6
+ .yardoc
7
+ .ruby-gemset
8
+ .ruby-version
9
+ Gemfile.lock
10
+ InstalledFiles
11
+ _yardoc
12
+ coverage
13
+ doc/
14
+ lib/bundler/man
15
+ pkg
16
+ rdoc
17
+ spec/reports
18
+ spec/data
19
+ test/tmp
20
+ test/version_tmp
21
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in passrock.gemspec
4
+ gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Bitium Inc.
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # Passrock
2
+
3
+ Ruby client library for programmatic access to the [Passrock Binary Database](https://www.passrock.com/demo.php).
4
+
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'passrock'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+
17
+ ## Usage
18
+
19
+ ### Plain Ol' Ruby (PORO)
20
+
21
+ require 'passrock'
22
+
23
+ passrock_db = Passrock::PasswordDb.new('/path/to/passrock/binary.dat', 'your private key')
24
+ passrock_db.secure?('password') # => false
25
+ passrock_db.insecure?('av3r^securePass') # => false
26
+
27
+
28
+ ### Ruby on Rails
29
+
30
+ This library provides a custom ActiveModel validation:
31
+
32
+ # Configure: config/initializers/passrock.rb
33
+ Passrock.configure do |config|
34
+ config.password_db = '/path/to/passrock/binary.dat'
35
+ config.private_key = 'your private key'
36
+ end
37
+
38
+ # Model
39
+ # e.g. app/models/user.rb
40
+ validates :password, :passrock_secure => true
41
+
42
+ # Customize the error message (see: http://guides.rubyonrails.org/i18n.html#error-message-scopes)
43
+ # e.g. config/locales/en.yml
44
+ activerecord:
45
+ errors:
46
+ messages:
47
+ passrock_secure: "appears to be a commonly used password"
48
+
49
+
50
+ ## Contributing
51
+
52
+ 1. Fork it
53
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
54
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
55
+ 4. Push to the branch (`git push origin my-new-feature`)
56
+ 5. Create new Pull Request
57
+
58
+
59
+ # Specs
60
+
61
+ To run the spec suite:
62
+
63
+ bundle install
64
+ cp .env.example .env # and change the env values
65
+ bundle exec rake spec
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
@@ -0,0 +1,13 @@
1
+ require 'passrock'
2
+ require 'benchmark'
3
+ require 'dotenv'
4
+
5
+ Dotenv.load
6
+
7
+ PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '../'))
8
+
9
+ passrock_db = Passrock::PasswordDb.new(ENV['PASSROCK_PASSWORD_DB'], ENV['PASSROCK_PRIVATE_KEY'])
10
+
11
+ Benchmark.bm do |x|
12
+ x.report("#find_by_binary_search\n") { puts "Password secure? #{passrock_db.secure?('password')}" }
13
+ end
@@ -0,0 +1,16 @@
1
+ require 'active_model/validations'
2
+
3
+ module ActiveModel
4
+ module Validations
5
+
6
+ class PassrockSecureValidator < ActiveModel::EachValidator
7
+
8
+ def validate_each(record, attribute, value)
9
+ passrock_db = Passrock::PasswordDb.new(Passrock.configuration.password_db, Passrock.configuration.private_key)
10
+ record.errors.add(attribute, :passrock_secure) if passrock_db.insecure?(value)
11
+ end
12
+
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ module Passrock
2
+ class Configuration
3
+
4
+ attr_accessor :password_db, :private_key
5
+
6
+ end
7
+ end
@@ -0,0 +1,75 @@
1
+ require 'base64'
2
+ require 'bcrypt'
3
+
4
+ module Passrock
5
+ class PasswordDb
6
+
7
+ RECORD_LENGTH = 23
8
+
9
+
10
+ def self.bcrypt_hash(secret, salt)
11
+ BCrypt::Engine.hash_secret(secret, "$2a$07$#{salt}")
12
+ end
13
+
14
+
15
+ attr_reader :filename, :private_key
16
+
17
+ def initialize(filename, private_key)
18
+ @filename = filename
19
+ @private_key = private_key
20
+ end
21
+
22
+ def password_in_searchable_form(password)
23
+ hashed_password = self.class.bcrypt_hash(password, private_key)
24
+
25
+ searchable = hashed_password[29..-1]
26
+ searchable.tr!('./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/')
27
+ searchable += '=' * (3 - (searchable.size + 3) % 4)
28
+ end
29
+
30
+ def secure?(password)
31
+ !find_by_binary_search(password)
32
+ end
33
+
34
+ def insecure?(password)
35
+ !secure?(password)
36
+ end
37
+
38
+
39
+ private
40
+
41
+ def total_records
42
+ # Minus 1 for length in file and 1 for 0-up counting
43
+ @total_records ||= (File.size(filename) / RECORD_LENGTH) - 2
44
+ end
45
+
46
+ def find_by_binary_search(password)
47
+ file = File.new(filename, 'rb')
48
+ target = password_in_searchable_form(password)
49
+
50
+ lo = 1 # start at 1 because the testKey is at 0
51
+ hi = total_records
52
+ while lo <= hi
53
+ mid = (lo + (hi - lo) / 2)
54
+ file.seek(RECORD_LENGTH * mid, IO::SEEK_SET)
55
+ midtest = file.read(RECORD_LENGTH)
56
+ raise 'Error reading binary file' if midtest.nil?
57
+
58
+ midtest = Base64.strict_encode64(midtest)
59
+
60
+ if ( (midtest <=> target) == 0 )
61
+ file.close
62
+ return true
63
+ elsif ( (midtest <=> target) < 0 )
64
+ lo = mid + 1
65
+ else
66
+ hi = mid - 1
67
+ end
68
+ end
69
+
70
+ file.close
71
+ return false
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,10 @@
1
+ module Passrock
2
+ class Railtie < ::Rails::Railtie
3
+
4
+ # Add load paths straight to I18n so engines and application can overwrite it.
5
+ require 'active_support/i18n'
6
+ I18n.load_path << File.join(File.dirname(__FILE__), '..', '..', 'locales', 'en.yml')
7
+
8
+ end
9
+ end
10
+
@@ -0,0 +1,3 @@
1
+ module Passrock
2
+ VERSION = '0.0.4'
3
+ end
data/lib/passrock.rb ADDED
@@ -0,0 +1,27 @@
1
+ require 'passrock/version'
2
+ require 'passrock/configuration'
3
+ require 'passrock/password_db'
4
+
5
+ require 'passrock/railtie' if defined?(::Rails::Railtie)
6
+ require 'active_model/validations/passrock_secure_validator' if defined?(::ActiveModel)
7
+
8
+ module Passrock
9
+
10
+ class << self
11
+
12
+ def configuration
13
+ @configuration ||= Configuration.new
14
+ end
15
+
16
+ def configure(&block)
17
+ yield(configuration)
18
+ configuration
19
+ end
20
+
21
+ def reset_configuration!
22
+ @configuration = nil
23
+ end
24
+
25
+ end
26
+
27
+ end
data/locales/en.yml ADDED
@@ -0,0 +1,4 @@
1
+ en:
2
+ errors:
3
+ messages:
4
+ passrock_secure: "appears to be a commonly used password"
data/passrock.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'passrock/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'passrock'
8
+ spec.version = Passrock::VERSION
9
+ spec.authors = ['Bitium, Inc']
10
+ spec.email = ['devops@bitium.com']
11
+ spec.description = %q{Client library for Passrock Binary Database}
12
+ spec.summary = %q{Ruby client library to access a Passrock (Passrock.com) binary database }
13
+ spec.homepage = 'https://github.com/bitium/passrock'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_runtime_dependency 'bcrypt-ruby'
22
+
23
+ spec.add_development_dependency 'rake'
24
+ spec.add_development_dependency 'rspec', '~> 2.14'
25
+ spec.add_development_dependency 'rails', '>= 3.2'
26
+ spec.add_development_dependency 'dotenv', '~> 0.8'
27
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ class TestRecord
4
+ include ActiveModel::Validations
5
+ attr_accessor :password
6
+
7
+ def initialize(password)
8
+ @password = password
9
+ end
10
+ end
11
+
12
+ describe ActiveModel::Validations::PassrockSecureValidator do
13
+ let(:password_db) { passrock_password_db }
14
+ let(:private_key) { passrock_private_key }
15
+ let(:field) { :password }
16
+
17
+ describe '#validate_each' do
18
+
19
+ before(:each) do
20
+ TestRecord.validates(field, :passrock_secure => true)
21
+
22
+ Passrock.configure do |config|
23
+ config.password_db = password_db
24
+ config.private_key = private_key
25
+ end
26
+
27
+ #I18n.backend.reload!
28
+ end
29
+
30
+ it 'validates the attribute with the Passrock DB for compromised passwords' do
31
+ model = TestRecord.new('password')
32
+ expect(model).to_not be_valid
33
+ expect(model.errors.messages[field]).to eq(['appears to be a commonly used password'])
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ describe Passrock::PasswordDb do
4
+ let(:password_db) { passrock_password_db }
5
+ let(:private_key) { passrock_private_key }
6
+ let(:insecure_password) { 'password' }
7
+ let(:secure_password) { 'BoatActKnowsDog' }
8
+
9
+
10
+ describe '.bcrypt_hash' do
11
+
12
+ it 'calculates and returns the bcrypt password hash given a secret and salt' do
13
+ secret = 'password'
14
+ salt = private_key
15
+ expect(described_class.bcrypt_hash(secret, salt)).to eq('$2a$07$c16iYVArVz3hYEvtakjiXO8jPyn2MxhVHlrY92EErobY/OCDNObhG')
16
+ end
17
+
18
+ end
19
+
20
+
21
+ describe '#password_in_searchable_form' do
22
+
23
+ it 'returns the given password in a searchable format' do
24
+ passrock = described_class.new(password_db, private_key)
25
+ expect(passrock.password_in_searchable_form(insecure_password)).to eq('+lR0p4OzjXJnta/4GGtqdaBQEFPQdjI=')
26
+ end
27
+
28
+ end
29
+
30
+ describe '#secure?' do
31
+ let(:passrock) { described_class.new(password_db, private_key) }
32
+
33
+ context 'when given password is present in the password database' do
34
+ it 'returns false' do
35
+ expect(passrock.secure?(insecure_password)).to be_false
36
+ end
37
+ end
38
+
39
+ context 'when given password does not appear in the password database' do
40
+ it 'returns true' do
41
+ expect(passrock.secure?(secure_password)).to be_true
42
+ end
43
+ end
44
+
45
+ context 'multiple sequential calls' do
46
+ it 'does not error out' do
47
+ expect {
48
+ passrock.secure?(secure_password)
49
+ passrock.secure?(insecure_password)
50
+ }.to_not raise_error
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+ describe '#insecure?' do
57
+ let(:passrock) { described_class.new(password_db, private_key) }
58
+
59
+ context 'when given password is present in the password database' do
60
+ it 'returns true' do
61
+ expect(passrock.insecure?(insecure_password)).to be_true
62
+ end
63
+ end
64
+
65
+ context 'when given password does not appear in the password database' do
66
+ it 'returns false' do
67
+ expect(passrock.insecure?(secure_password)).to be_false
68
+ end
69
+ end
70
+ end
71
+
72
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Passrock do
4
+
5
+ describe '.configure' do
6
+
7
+ before(:each) do
8
+ Passrock.reset_configuration!
9
+ end
10
+
11
+ it 'allows configuration to be set with a block' do
12
+ Passrock.configure do |config|
13
+ config.password_db = '/path/to/db'
14
+ config.private_key = 'abc12345'
15
+ end
16
+
17
+ expect(Passrock.configuration.password_db).to eq('/path/to/db')
18
+ expect(Passrock.configuration.private_key).to eq('abc12345')
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,32 @@
1
+ require 'active_model/railtie'
2
+ require 'passrock'
3
+ require 'dotenv'
4
+
5
+ Dotenv.load
6
+
7
+ PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '../'))
8
+
9
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
10
+ RSpec.configure do |config|
11
+ config.treat_symbols_as_metadata_keys_with_true_values = true
12
+ config.run_all_when_everything_filtered = true
13
+ config.filter_run :focus
14
+
15
+ # Run specs in random order to surface order dependencies. If you find an
16
+ # order dependency and want to debug it, you can fix the order by providing
17
+ # the seed, which is printed after each run.
18
+ # --seed 1234
19
+ config.order = 'random'
20
+ end
21
+
22
+
23
+
24
+ # Helpers
25
+
26
+ def passrock_password_db
27
+ ENV['PASSROCK_PASSWORD_DB']
28
+ end
29
+
30
+ def passrock_private_key
31
+ ENV['PASSROCK_PRIVATE_KEY']
32
+ end
metadata ADDED
@@ -0,0 +1,138 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: passrock
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Bitium, Inc
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-09-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bcrypt-ruby
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '2.14'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '2.14'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '3.2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '3.2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: dotenv
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '0.8'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '0.8'
83
+ description: Client library for Passrock Binary Database
84
+ email:
85
+ - devops@bitium.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - .env.example
91
+ - .gitignore
92
+ - .rspec
93
+ - Gemfile
94
+ - MIT-LICENSE
95
+ - README.md
96
+ - Rakefile
97
+ - benchmark/binary_search_test.rb
98
+ - lib/active_model/validations/passrock_secure_validator.rb
99
+ - lib/passrock.rb
100
+ - lib/passrock/configuration.rb
101
+ - lib/passrock/password_db.rb
102
+ - lib/passrock/railtie.rb
103
+ - lib/passrock/version.rb
104
+ - locales/en.yml
105
+ - passrock.gemspec
106
+ - spec/active_model/validations/passrock_secure_validator_spec.rb
107
+ - spec/passrock/password_db_spec.rb
108
+ - spec/passrock_spec.rb
109
+ - spec/spec_helper.rb
110
+ homepage: https://github.com/bitium/passrock
111
+ licenses:
112
+ - MIT
113
+ metadata: {}
114
+ post_install_message:
115
+ rdoc_options: []
116
+ require_paths:
117
+ - lib
118
+ required_ruby_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - '>='
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ required_rubygems_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ requirements: []
129
+ rubyforge_project:
130
+ rubygems_version: 2.0.3
131
+ signing_key:
132
+ specification_version: 4
133
+ summary: Ruby client library to access a Passrock (Passrock.com) binary database
134
+ test_files:
135
+ - spec/active_model/validations/passrock_secure_validator_spec.rb
136
+ - spec/passrock/password_db_spec.rb
137
+ - spec/passrock_spec.rb
138
+ - spec/spec_helper.rb