go_secure 0.62 → 0.70
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 +5 -5
- data/lib/go_secure.rb +116 -12
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6c1ac3e5ca4f3cec1163eaaf94c96aeecbf9d7598a0b36b0a88b62c02ce0fdf6
|
4
|
+
data.tar.gz: 8ed2bd8c670d7903aac0c7ae127f121d1e03d39d46aeb104d6d005141b6892d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz: '
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '06197b6cc0e35b7ba5fe6547ad58b27fff19726fe6a2508af31595c059f8f0ce23c589111c77f8a22c4de50d952a7610ea9fdc6aa187ef4b481d2df2885d15e7'
|
7
|
+
data.tar.gz: 493403cce547664bf0f29bf581ca0ee68af32ddb8d70637d37fe33fa65ea95eed5a1071cba08b8a2642b6d53120da48424d38d7f7bc74d82176ec5f4abc76898
|
data/lib/go_secure.rb
CHANGED
@@ -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
|
28
|
+
c = OpenSSL::Cipher.new('aes-256-cbc')
|
24
29
|
c.encrypt
|
25
|
-
|
26
|
-
c.
|
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
|
43
|
+
c = OpenSSL::Cipher.new('aes-256-cbc')
|
36
44
|
c.decrypt
|
37
|
-
|
38
|
-
c.
|
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.
|
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
|
-
|
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
|
-
|
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.
|
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:
|
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.
|
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: []
|