go_secure 0.62 → 0.70
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|