sequel_password 0.1 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c7be80a93422a9c18bd61e2d309b61481fb4c4d1
4
- data.tar.gz: b89e1934f8373ba7e341d50312b1620574f93f19
3
+ metadata.gz: 536c42e3a0e81d54a1ede80ebf0d02384efb8e9d
4
+ data.tar.gz: 85510cee1cc2c043139dee879e7b5eef2519436a
5
5
  SHA512:
6
- metadata.gz: a15ae5358ab1e5601c50dc6cc4c5b10bd4c223c3f3e5d2726e8a022b8dd28989a24e8b7b0e5321add1835549fcc5bbc1277e8df0ee12866db2748bb090e07863
7
- data.tar.gz: 1014dcda3e264885bb94301736b00bfce78f574444919b11d6f0c71c53079192fb81345403385cc838e552ddc79d021d65d2acc7a7ede82d426af3822ef7909a
6
+ metadata.gz: 4188cd381e1de2ed42f27881271bbdc385090cd4249c5b8ae7c67dc20f09fc7728285992e6fec3b5fc9b26cfce117a4db4446e0b6447dd9f19fa686ae8b524fb
7
+ data.tar.gz: 729291c54d8c8bdb03198ce58ddebc5909f9c16af68e5e0691c4dffee8063b1e5d856c5ba3a075c4e231f0ea3497a6af1da1d65d8100478ed0decdad11123ceb
data/.gitignore CHANGED
@@ -1 +1,2 @@
1
1
  coverage
2
+ *.gem
data/Gemfile.lock CHANGED
@@ -2,9 +2,9 @@ PATH
2
2
  remote: .
3
3
  specs:
4
4
  sequel_password (0.1)
5
- bcrypt (~> 3.1.10)
5
+ bcrypt (~> 3.1, >= 3.1.10)
6
6
  pbkdf2-ruby (~> 0.2.1)
7
- sequel (~> 4.21.0)
7
+ sequel (~> 4.21, >= 4.21.0)
8
8
 
9
9
  GEM
10
10
  remote: https://rubygems.org/
@@ -39,7 +39,7 @@ PLATFORMS
39
39
  ruby
40
40
 
41
41
  DEPENDENCIES
42
- rspec (~> 3.2.0)
42
+ rspec (~> 3.2, >= 3.2.0)
43
43
  sequel_password!
44
44
  simplecov (~> 0.9.2)
45
- sqlite3 (~> 1.3.10)
45
+ sqlite3 (~> 1.3, >= 1.3.10)
data/README.md CHANGED
@@ -2,3 +2,5 @@
2
2
 
3
3
  This sequel plugin adds authentication and password hashing to Sequel models.
4
4
  It supports pbkdf2 and bcrypt hashers.
5
+
6
+ # Usage
@@ -0,0 +1,118 @@
1
+ require "base64"
2
+ require "bcrypt"
3
+ require "openssl"
4
+ require "pbkdf2"
5
+ require "securerandom"
6
+
7
+ module Sequel
8
+ module Plugins
9
+ module Password
10
+ class Hasher
11
+ attr_reader :algorithm
12
+
13
+ def salt
14
+ # 72 bits
15
+ SecureRandom.hex(9)
16
+ end
17
+
18
+ def verify(password, encoded)
19
+ raise NotImplementedError
20
+ end
21
+
22
+ def encode(password, salt)
23
+ raise NotImplementedError
24
+ end
25
+
26
+ def must_update(encoded)
27
+ false
28
+ end
29
+
30
+ private
31
+
32
+ def constant_time_compare(a, b)
33
+ check = a.bytesize ^ b.bytesize
34
+ a.bytes.zip(b.bytes) { |x, y| check |= x ^ y }
35
+ check == 0
36
+ end
37
+ end
38
+
39
+ class PBKDF2Hasher < Hasher
40
+ def initialize
41
+ @algorithm = :pbkdf2_sha256
42
+ @iterations = 24000
43
+ @digest = OpenSSL::Digest::SHA256.new
44
+ end
45
+
46
+ def encode(password, salt, iterations = nil)
47
+ iterations = @iterations if iterations.nil?
48
+ hash = PBKDF2.new(password: password, salt: salt,
49
+ iterations: iterations, hash_function: @digest)
50
+ hash = Base64.strict_encode64(hash.value)
51
+ "#{@algorithm}$#{iterations}$#{salt}$#{hash}"
52
+ end
53
+
54
+ def verify(password, encoded)
55
+ algorithm, iterations, salt, hash = encoded.split('$', 4)
56
+ hash = encode(password, salt, iterations.to_i)
57
+ constant_time_compare(encoded, hash)
58
+ end
59
+
60
+ def must_update(encoded)
61
+ algorithm, iterations, salt, hash = encoded.split('$', 4)
62
+ iterations.to_i != @iterations
63
+ end
64
+ end
65
+
66
+ class BCryptSHA256Hasher < Hasher
67
+ def initialize
68
+ @algorithm = :bcrypt_sha256
69
+ @cost = 12
70
+ @digest = OpenSSL::Digest::SHA256.new
71
+ end
72
+
73
+ def salt
74
+ BCrypt::Engine.generate_salt(@cost)
75
+ end
76
+
77
+ def encode(password, salt)
78
+ password = @digest.digest(password) unless @digest.nil?
79
+ hash = BCrypt::Engine.hash_secret(password, salt)
80
+ "#{@algorithm}$#{hash}"
81
+ end
82
+
83
+ def verify(password, encoded)
84
+ algorithm, data = encoded.split('$', 2)
85
+ password = @digest.digest(password) unless @digest.nil?
86
+ hash = BCrypt::Engine.hash_secret(password, data)
87
+ constant_time_compare(data, hash)
88
+ end
89
+ end
90
+
91
+ class BCryptHasher < BCryptSHA256Hasher
92
+ def initialize
93
+ @algorithm = :bcrypt
94
+ @cost = 12
95
+ @digest = nil
96
+ end
97
+ end
98
+
99
+ class SHA1Hasher < Hasher
100
+ def initialize
101
+ @algorithm = :sha1
102
+ @digest = OpenSSL::Digest::SHA1.new
103
+ end
104
+
105
+ def encode(password, salt)
106
+ hash = @digest.digest(salt + password).unpack('H*').first
107
+ "#{@algorithm}$#{salt}$#{hash}"
108
+ end
109
+
110
+ def verify(password, encoded)
111
+ algorithm, salt, hash = encoded.split('$', 3)
112
+ hash = encode(password, salt)
113
+ constant_time_compare(encoded, hash)
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -1,8 +1,5 @@
1
- require "base64"
2
- require "bcrypt"
3
- require "openssl"
4
- require "pbkdf2"
5
1
  require "securerandom"
2
+ require "sequel_password/hashers"
6
3
 
7
4
  module Sequel
8
5
  module Plugins
@@ -33,10 +30,6 @@ module Sequel
33
30
  hasher(algorithm).encode(password, salt)
34
31
  end
35
32
 
36
- def hasher(algorithm = :default)
37
- @hashers.fetch(algorithm.to_sym, @hashers.values.first)
38
- end
39
-
40
33
  def usable_password?(encoded)
41
34
  return false if encoded.nil? || encoded.start_with?("!")
42
35
 
@@ -58,6 +51,12 @@ module Sequel
58
51
 
59
52
  correct
60
53
  end
54
+
55
+ private
56
+
57
+ def hasher(algorithm = :default)
58
+ @hashers.fetch(algorithm.to_sym, @hashers.values.first)
59
+ end
61
60
  end
62
61
 
63
62
  module InstanceMethods
@@ -74,113 +73,6 @@ module Sequel
74
73
  send("#{model.column}=", model.make_password(nil))
75
74
  end
76
75
  end
77
-
78
- class Hasher
79
- attr_reader :algorithm
80
-
81
- def salt
82
- # 72 bits
83
- SecureRandom.hex(9)
84
- end
85
-
86
- def verify(password, encoded)
87
- raise NotImplementedError
88
- end
89
-
90
- def encode(password, salt)
91
- raise NotImplementedError
92
- end
93
-
94
- def must_update(encoded)
95
- false
96
- end
97
-
98
- private
99
-
100
- def constant_time_compare(a, b)
101
- check = a.bytesize ^ b.bytesize
102
- a.bytes.zip(b.bytes) { |x, y| check |= x ^ y }
103
- check == 0
104
- end
105
- end
106
-
107
- class PBKDF2Hasher < Hasher
108
- def initialize
109
- @algorithm = :pbkdf2_sha256
110
- @iterations = 24000
111
- @digest = OpenSSL::Digest::SHA256.new
112
- end
113
-
114
- def encode(password, salt, iterations = nil)
115
- iterations = @iterations if iterations.nil?
116
- hash = PBKDF2.new(password: password, salt: salt,
117
- iterations: iterations, hash_function: @digest)
118
- hash = Base64.strict_encode64(hash.value)
119
- "#{@algorithm}$#{iterations}$#{salt}$#{hash}"
120
- end
121
-
122
- def verify(password, encoded)
123
- algorithm, iterations, salt, hash = encoded.split('$', 4)
124
- hash = encode(password, salt, iterations.to_i)
125
- constant_time_compare(encoded, hash)
126
- end
127
-
128
- def must_update(encoded)
129
- algorithm, iterations, salt, hash = encoded.split('$', 4)
130
- iterations.to_i != @iterations
131
- end
132
- end
133
-
134
- class BCryptSHA256Hasher < Hasher
135
- def initialize
136
- @algorithm = :bcrypt_sha256
137
- @cost = 12
138
- @digest = OpenSSL::Digest::SHA256.new
139
- end
140
-
141
- def salt
142
- BCrypt::Engine.generate_salt(@cost)
143
- end
144
-
145
- def encode(password, salt)
146
- password = @digest.digest(password) unless @digest.nil?
147
- hash = BCrypt::Engine.hash_secret(password, salt)
148
- "#{@algorithm}$#{hash}"
149
- end
150
-
151
- def verify(password, encoded)
152
- algorithm, data = encoded.split('$', 2)
153
- password = @digest.digest(password) unless @digest.nil?
154
- hash = BCrypt::Engine.hash_secret(password, data)
155
- constant_time_compare(data, hash)
156
- end
157
- end
158
-
159
- class BCryptHasher < BCryptSHA256Hasher
160
- def initialize
161
- @algorithm = :bcrypt
162
- @cost = 12
163
- @digest = nil
164
- end
165
- end
166
-
167
- class SHA1Hasher < Hasher
168
- def initialize
169
- @algorithm = :sha1
170
- @digest = OpenSSL::Digest::SHA1.new
171
- end
172
-
173
- def encode(password, salt)
174
- hash = @digest.digest(salt + password).unpack('H*').first
175
- "#{@algorithm}$#{salt}$#{hash}"
176
- end
177
-
178
- def verify(password, encoded)
179
- algorithm, salt, hash = encoded.split('$', 3)
180
- hash = encode(password, salt)
181
- constant_time_compare(encoded, hash)
182
- end
183
- end
184
76
  end
185
77
  end
186
78
  end
@@ -13,11 +13,11 @@ Gem::Specification.new do |gem|
13
13
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
14
  gem.name = "sequel_password"
15
15
  gem.require_paths = ["lib"]
16
- gem.version = '0.1'
16
+ gem.version = '0.1.1'
17
17
 
18
18
  gem.add_runtime_dependency 'sequel', '~> 4.21', '>= 4.21.0'
19
19
  gem.add_runtime_dependency 'bcrypt', '~> 3.1', '>= 3.1.10'
20
- gem.add_runtime_dependency 'pbkf2-ruby', '~> 0.2.1'
20
+ gem.add_runtime_dependency 'pbkdf2-ruby', '~> 0.2.1'
21
21
 
22
22
  gem.add_development_dependency 'rspec', '~> 3.2', '>= 3.2.0'
23
23
  gem.add_development_dependency 'simplecov', '~> 0.9.2'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel_password
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.1'
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Timothée Peignier
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-04 00:00:00.000000000 Z
11
+ date: 2015-04-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -51,7 +51,7 @@ dependencies:
51
51
  - !ruby/object:Gem::Version
52
52
  version: 3.1.10
53
53
  - !ruby/object:Gem::Dependency
54
- name: pbkf2-ruby
54
+ name: pbkdf2-ruby
55
55
  requirement: !ruby/object:Gem::Requirement
56
56
  requirements:
57
57
  - - "~>"
@@ -132,6 +132,7 @@ files:
132
132
  - Gemfile.lock
133
133
  - README.md
134
134
  - lib/sequel_password.rb
135
+ - lib/sequel_password/hashers.rb
135
136
  - sequel_password.gemspec
136
137
  - spec/sequel_password_spec.rb
137
138
  - spec/spec_helper.rb