go_secure 0.62 → 0.70

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +5 -5
  2. data/lib/go_secure.rb +116 -12
  3. metadata +7 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 23672006525e9b8d00c32febe3e51c7f0b7f622a
4
- data.tar.gz: 9cf3d608a364304aa1f1f4d57be6d5e9d429b767
2
+ SHA256:
3
+ metadata.gz: 6c1ac3e5ca4f3cec1163eaaf94c96aeecbf9d7598a0b36b0a88b62c02ce0fdf6
4
+ data.tar.gz: 8ed2bd8c670d7903aac0c7ae127f121d1e03d39d46aeb104d6d005141b6892d7
5
5
  SHA512:
6
- metadata.gz: '019ef5cccca1afc672ce75c5370d63ee4135e1a584179a9eb7a056f54c3a4c9bd72cbdb2194e3e0dafb440aaebefbf867c9a928033a7110cc30af8abdc2aba27'
7
- data.tar.gz: c01c6899abc3711302d987daa9d23a7f5666c6c95d142bdcfc0dbade4d3cbee33ca0d20ca57eecb9c9b1d2c31344a045cecee41074012c2f27409f3870555237
6
+ metadata.gz: '06197b6cc0e35b7ba5fe6547ad58b27fff19726fe6a2508af31595c059f8f0ce23c589111c77f8a22c4de50d952a7610ea9fdc6aa187ef4b481d2df2885d15e7'
7
+ data.tar.gz: 493403cce547664bf0f29bf581ca0ee68af32ddb8d70637d37fe33fa65ea95eed5a1071cba08b8a2642b6d53120da48424d38d7f7bc74d82176ec5f4abc76898
@@ -13,17 +13,25 @@ module GoSecure
13
13
  digest = OpenSSL::Digest::SHA512.new(encryption_key || self.encryption_key)
14
14
  res = Base64.urlsafe_encode64(OpenSSL::PKCS5.pbkdf2_hmac(str.to_s, salt.to_s, 100000, digest.digest_length, digest))
15
15
  end
16
+
17
+ def self.lite_hmac(str, salt, level, encryption_key=nil)
18
+ raise "invalid level" unless level == 1
19
+ OpenSSL::HMAC.hexdigest('SHA512', OpenSSL::HMAC.hexdigest('SHA512', str.to_s, salt.to_s), encryption_key || self.encryption_key)
20
+ end
16
21
 
17
22
  def self.nonce(str)
18
23
  Digest::SHA512.hexdigest(str.to_s + Time.now.to_i.to_s + rand(999999).to_s + self.encryption_key)[0, 24]
19
24
  end
20
25
 
21
- def self.encrypt(str, ref, encryption_key=nil)
26
+ def self.encrypt(str, ref, encryption_key=nil, iv=nil)
22
27
  require 'base64'
23
- c = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
28
+ c = OpenSSL::Cipher.new('aes-256-cbc')
24
29
  c.encrypt
25
- c.key = Digest::SHA2.hexdigest(ref + "_" + (encryption_key || self.encryption_key))
26
- c.iv = iv = c.random_iv
30
+ sha = Digest::SHA2.hexdigest(ref + "_" + (encryption_key || self.encryption_key))
31
+ c.key = sha[0..31]
32
+ raise "invalid iv" if iv && iv.length != 16
33
+ iv = iv || c.random_iv
34
+ c.iv = iv
27
35
  e = c.update(str)
28
36
  e << c.final
29
37
  res = [Base64.encode64(e), Base64.encode64(iv)]
@@ -32,10 +40,13 @@ module GoSecure
32
40
 
33
41
  def self.decrypt(str, salt, ref, encryption_key=nil)
34
42
  require 'base64'
35
- c = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
43
+ c = OpenSSL::Cipher.new('aes-256-cbc')
36
44
  c.decrypt
37
- c.key = Digest::SHA2.hexdigest(ref + "_" + (encryption_key || self.encryption_key))
38
- c.iv = Base64.decode64(salt)
45
+ sha = Digest::SHA2.hexdigest(ref + "_" + (encryption_key || self.encryption_key))
46
+ c.key = sha[0..31]
47
+ iv = Base64.decode64(salt)
48
+
49
+ c.iv = iv[0..15]
39
50
  d = c.update(Base64.decode64(str))
40
51
  d << c.final
41
52
  d.to_s
@@ -47,7 +58,7 @@ module GoSecure
47
58
  # pw['hash_type'] = 'sha512'
48
59
  # pw['hash_type'] = 'bcrypt'
49
60
  pw['hash_type'] = 'pbkdf2-sha256-2'
50
- pw['salt'] = Digest::MD5.hexdigest(OpenSSL::Random.pseudo_bytes(4) + Time.now.to_i.to_s + self.encryption_key + "pw" + OpenSSL::Random.pseudo_bytes(16))
61
+ pw['salt'] = Digest::MD5.hexdigest(OpenSSL::Random.random_bytes(4) + Time.now.to_i.to_s + self.encryption_key + "pw" + OpenSSL::Random.random_bytes(16))
51
62
  # pw['hashed_password'] = Digest::SHA512.hexdigest(self.encryption_key + pw['salt'] + password.to_s)
52
63
  # salted = Digest::SHA256.hexdigest(self.encryption_key + pw['salt'] + password.to_s)
53
64
  # pw['hashed_password'] = BCrypt::Password.create(salted)
@@ -109,7 +120,8 @@ module GoSecure
109
120
 
110
121
  def self.browser_token
111
122
  # TODO: checks around whether it's actually a web browser??
112
- stamp = Time.now.strftime('%Y%j')
123
+ day = Time.now.strftime('%j')
124
+ stamp = "#{Time.now.year}#{(Time.now.yday / 366.0 * 100.0).to_i.to_s.rjust(2, '0')}"
113
125
  stamp += '-' + GoSecure.sha512(stamp, 'browser_token')
114
126
  end
115
127
 
@@ -121,7 +133,8 @@ module GoSecure
121
133
  def self.valid_browser_token?(token)
122
134
  return false if !token || token.length == 0 || !token.match(/-/)
123
135
  stamp, hash = token.split(/-/, 2)
124
- if Time.now.strftime('%Y%j').to_i - stamp.to_i < 14 # 14 days?!
136
+ current_stamp = "#{Time.now.year}#{(Time.now.yday / 366.0 * 100.0).to_i.to_s.rjust(2, '0')}"
137
+ if current_stamp.to_i - stamp.to_i < (14/365.0*100.0) # 14 days?!
125
138
  return valid_browser_token_signature?(token)
126
139
  end
127
140
  false
@@ -135,10 +148,10 @@ module GoSecure
135
148
  def self.load(str)
136
149
  return nil unless str
137
150
  if str.match(/^\*\*/)
138
- Oj.load(str[2..-1])
151
+ Oj.load(str[2..-1], mode: :compat)
139
152
  else
140
153
  salt, secret = str.split(/--/, 2)
141
- Oj.load(GoSecure.decrypt(secret, salt, "secure_json"))
154
+ Oj.load(GoSecure.decrypt(secret, salt, "secure_json"), mode: :compat)
142
155
  end
143
156
  end
144
157
 
@@ -157,4 +170,95 @@ module GoSecure
157
170
  end
158
171
  end
159
172
  end
173
+
174
+ module SerializeInstanceMethods
175
+ def load_secure_object
176
+ @secure_object_json = nil.to_json
177
+ if self.id
178
+ attr = read_attribute(self.class.secure_column) || (!self.respond_to?(:secure_column_value) && self.send(self.class.secure_column)) || (@secure_object.is_a?(String) && @secure_object) || nil
179
+ if attr && attr.match(/\s*^{/)
180
+ @secure_object = JSON.parse(attr)
181
+ else
182
+ @secure_object = GoSecure::SecureJson.load(attr)
183
+ end
184
+ @secure_object_json = @secure_object.to_json
185
+ @loaded_secure_object = true
186
+ end
187
+ true
188
+ end
189
+
190
+ # If the serialized data has changed since initialize and paper_trail
191
+ # is configured, then we need to manually mark the column as dirty
192
+ # to make sure a proper paper_trail is maintained
193
+ def mark_changed_secure_object_hash
194
+ if !send("#{self.class.secure_column}_changed?")
195
+ json = @secure_object.to_json
196
+ if json != @secure_object_json
197
+ send("#{self.class.secure_column}_will_change!")
198
+ end
199
+ end
200
+ true
201
+ end
202
+
203
+ def persist_secure_object
204
+ self.class.more_before_saves ||= []
205
+ self.class.more_before_saves.each do |method|
206
+ res = send(method)
207
+ return false if res == false
208
+ end
209
+ mark_changed_secure_object_hash
210
+ if send("#{self.class.secure_column}_changed?")
211
+ secure = GoSecure::SecureJson.dump(@secure_object)
212
+ @secure_object = GoSecure::SecureJson.load(secure)
213
+ write_attribute(self.class.secure_column, secure)
214
+ end
215
+ true
216
+ end
217
+ end
218
+
219
+ module SerializeClassMethods
220
+ def secure_serialize(column)
221
+ raise "only one secure column per record! (yes I'm lazy)" if self.respond_to?(:secure_column) && self.secure_column
222
+ cattr_accessor :secure_column
223
+ cattr_accessor :more_before_saves
224
+ self.secure_column = column
225
+ prepend SecureSerializeHelpers
226
+
227
+ before_save :persist_secure_object
228
+ define_singleton_method(:before_save) do |*args|
229
+ raise "only simple before_save calls after secure_serialize: #{args.to_json}" unless args.length == 1 && args[0].is_a?(Symbol)
230
+ self.more_before_saves ||= []
231
+ self.more_before_saves << args[0]
232
+ end
233
+ define_method("secure_column_value") do
234
+ nil
235
+ end
236
+ define_method("#{column}") do
237
+ load_secure_object unless @loaded_secure_object
238
+ @secure_object
239
+ end
240
+ define_method("#{column}=") do |val|
241
+ @loaded_secure_object = true
242
+ @secure_object = val
243
+ end
244
+ # Commented out because eager-loading an encrypted data column is not efficient
245
+ # after_initialize :load_secure_object
246
+ end
247
+ end
248
+
249
+ module SecureSerializeHelpers
250
+ def reload(*args)
251
+ res = super
252
+ load_secure_object
253
+ res
254
+ end
255
+
256
+ def []=(*args)
257
+ if args[0].to_s == self.class.secure_column
258
+ send("#{self.class.secure_column}=", args[1])
259
+ else
260
+ super
261
+ end
262
+ end
263
+ end
160
264
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: go_secure
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.62'
4
+ version: '0.70'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Whitmer
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-14 00:00:00.000000000 Z
11
+ date: 2020-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oj
@@ -66,7 +66,7 @@ homepage: https://github.com/CoughDrop/obf
66
66
  licenses:
67
67
  - MIT
68
68
  metadata: {}
69
- post_install_message:
69
+ post_install_message:
70
70
  rdoc_options: []
71
71
  require_paths:
72
72
  - lib
@@ -81,9 +81,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  requirements: []
84
- rubyforge_project:
85
- rubygems_version: 2.5.2
86
- signing_key:
84
+ rubyforge_project:
85
+ rubygems_version: 2.7.6
86
+ signing_key:
87
87
  specification_version: 4
88
88
  summary: Go Secure
89
89
  test_files: []