symmetric-encryption 4.2.1 → 4.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/symmetric_encryption.rb +6 -2
- data/lib/symmetric_encryption/{railties → active_record}/attr_encrypted.rb +16 -5
- data/lib/symmetric_encryption/active_record/encrypted_attribute.rb +37 -0
- data/lib/symmetric_encryption/cipher.rb +3 -3
- data/lib/symmetric_encryption/core.rb +4 -0
- data/lib/symmetric_encryption/railtie.rb +7 -7
- data/lib/symmetric_encryption/symmetric_encryption.rb +33 -19
- data/lib/symmetric_encryption/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5499f0c6e33fc5eee0a2295623edd3bf35a247e1a6263a3e93f2c4e57219f22
|
4
|
+
data.tar.gz: ea3495cf8f5fe6b388725cd424ed13dc8b982c4ad225e78c7056f8d0f0d70cab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a8a920045c6b813bb55e8a518727ffdaf03b0b5857f5326d8b6003946d81fb162f28eea69617934622626de66cbfbeaf27b464c5d7baa21e07332e2c7098f7e4
|
7
|
+
data.tar.gz: bb2a832909e3a81b1e357a4ec650e7f1fd93e81ab08a0a0f3664b586bc0bf60f1a821c26831f456138e77a7a29575bc976890f608ac10461a51e5fd86dbd2699
|
data/lib/symmetric_encryption.rb
CHANGED
@@ -10,10 +10,14 @@ end
|
|
10
10
|
begin
|
11
11
|
require 'active_support'
|
12
12
|
ActiveSupport.on_load(:active_record) do
|
13
|
-
require 'symmetric_encryption/
|
13
|
+
require 'symmetric_encryption/active_record/attr_encrypted'
|
14
14
|
require 'symmetric_encryption/railties/symmetric_encryption_validator'
|
15
15
|
|
16
|
-
ActiveRecord::
|
16
|
+
if ActiveRecord.version >= Gem::Version.new('5.0.0')
|
17
|
+
ActiveRecord::Type.register(:encrypted, SymmetricEncryption::ActiveRecord::EncryptedAttribute)
|
18
|
+
end
|
19
|
+
|
20
|
+
ActiveRecord::Base.include(SymmetricEncryption::ActiveRecord::AttrEncrypted)
|
17
21
|
end
|
18
22
|
|
19
23
|
ActiveSupport.on_load(:mongoid) do
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module SymmetricEncryption
|
2
|
-
module
|
2
|
+
module ActiveRecord
|
3
3
|
module AttrEncrypted
|
4
4
|
def self.included(base)
|
5
5
|
base.extend ClassMethods
|
@@ -39,7 +39,7 @@ module SymmetricEncryption
|
|
39
39
|
# compression
|
40
40
|
# Note: Adds a 6 byte header prior to encoding, only if :random_iv is false
|
41
41
|
# Default: false
|
42
|
-
def attr_encrypted(*
|
42
|
+
def attr_encrypted(*attributes, random_iv: nil, type: :string, compress: false)
|
43
43
|
# Ensure ActiveRecord has created all its methods first
|
44
44
|
# Ignore failures since the table may not yet actually exist
|
45
45
|
begin
|
@@ -48,10 +48,21 @@ module SymmetricEncryption
|
|
48
48
|
nil
|
49
49
|
end
|
50
50
|
|
51
|
-
|
51
|
+
random_iv = true if random_iv.nil? && SymmetricEncryption.randomize_iv?
|
52
52
|
|
53
|
-
|
54
|
-
|
53
|
+
if random_iv.nil?
|
54
|
+
warn("attr_encrypted() no longer allows a default value for option `random_iv`. Add `random_iv: false` if it is required.")
|
55
|
+
end
|
56
|
+
|
57
|
+
attributes.each do |attribute|
|
58
|
+
SymmetricEncryption::Generator.generate_decrypted_accessors(
|
59
|
+
self,
|
60
|
+
attribute,
|
61
|
+
"encrypted_#{attribute}",
|
62
|
+
random_iv: random_iv,
|
63
|
+
type: type,
|
64
|
+
compress: compress
|
65
|
+
)
|
55
66
|
encrypted_attributes[attribute.to_sym] = "encrypted_#{attribute}".to_sym
|
56
67
|
end
|
57
68
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module SymmetricEncryption
|
2
|
+
module ActiveRecord
|
3
|
+
class EncryptedAttribute < ::ActiveModel::Type::String
|
4
|
+
def initialize(random_iv: true, compress: false, type: :string)
|
5
|
+
@random_iv = random_iv
|
6
|
+
@compress = compress
|
7
|
+
@encrypted_type = type
|
8
|
+
end
|
9
|
+
|
10
|
+
def deserialize(value)
|
11
|
+
return if value.nil?
|
12
|
+
|
13
|
+
SymmetricEncryption.decrypt(value, type: encrypted_type)
|
14
|
+
end
|
15
|
+
|
16
|
+
def serialize(value)
|
17
|
+
return if value.nil?
|
18
|
+
|
19
|
+
SymmetricEncryption.encrypt(
|
20
|
+
value,
|
21
|
+
type: encrypted_type,
|
22
|
+
compress: compress,
|
23
|
+
random_iv: random_iv
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# Symmetric Encryption uses coercible gem to handle casting
|
30
|
+
def cast_value(value)
|
31
|
+
value
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_reader :random_iv, :compress, :encrypted_type
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -58,7 +58,7 @@ module SymmetricEncryption
|
|
58
58
|
# Return as raw binary data string. Note: String can contain embedded nulls
|
59
59
|
# Default: :base64strict
|
60
60
|
#
|
61
|
-
# version [
|
61
|
+
# version [Integer]
|
62
62
|
# Optional. The version number of this encryption key
|
63
63
|
# Used by SymmetricEncryption to select the correct key when decrypting data
|
64
64
|
# Valid Range: 0..255
|
@@ -131,7 +131,7 @@ module SymmetricEncryption
|
|
131
131
|
# * Should only be used for large strings since compression overhead and
|
132
132
|
# the overhead of adding the encryption header may exceed any benefits of
|
133
133
|
# compression
|
134
|
-
def encrypt(str, random_iv:
|
134
|
+
def encrypt(str, random_iv: SymmetricEncryption.randomize_iv?, compress: false, header: always_add_header)
|
135
135
|
return if str.nil?
|
136
136
|
|
137
137
|
str = str.to_s
|
@@ -246,7 +246,7 @@ module SymmetricEncryption
|
|
246
246
|
# Default: `always_add_header`
|
247
247
|
#
|
248
248
|
# See #encrypt to encrypt and encode the result as a string.
|
249
|
-
def binary_encrypt(str, random_iv:
|
249
|
+
def binary_encrypt(str, random_iv: SymmetricEncryption.randomize_iv?, compress: false, header: always_add_header)
|
250
250
|
return if str.nil?
|
251
251
|
|
252
252
|
string = str.to_s
|
@@ -13,6 +13,7 @@ module SymmetricEncryption
|
|
13
13
|
autoload :Coerce, 'symmetric_encryption/coerce'
|
14
14
|
autoload :Config, 'symmetric_encryption/config'
|
15
15
|
autoload :Encoder, 'symmetric_encryption/encoder'
|
16
|
+
autoload :EncryptedStringType, 'symmetric_encryption/types/encrypted_string_type'
|
16
17
|
autoload :Generator, 'symmetric_encryption/generator'
|
17
18
|
autoload :Header, 'symmetric_encryption/header'
|
18
19
|
autoload :Key, 'symmetric_encryption/key'
|
@@ -21,6 +22,9 @@ module SymmetricEncryption
|
|
21
22
|
autoload :Writer, 'symmetric_encryption/writer'
|
22
23
|
autoload :CLI, 'symmetric_encryption/cli'
|
23
24
|
autoload :Keystore, 'symmetric_encryption/keystore'
|
25
|
+
module ActiveRecord
|
26
|
+
autoload :EncryptedAttribute, 'symmetric_encryption/active_record/encrypted_attribute'
|
27
|
+
end
|
24
28
|
module Utils
|
25
29
|
autoload :Aws, 'symmetric_encryption/utils/aws'
|
26
30
|
autoload :Files, 'symmetric_encryption/utils/files'
|
@@ -29,13 +29,15 @@ module SymmetricEncryption #:nodoc:
|
|
29
29
|
config.before_configuration do
|
30
30
|
# Check if already configured
|
31
31
|
unless ::SymmetricEncryption.cipher?
|
32
|
-
app_name
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
app_name = Rails::Application.subclasses.first.parent.to_s.underscore
|
33
|
+
env_var = ENV['SYMMETRIC_ENCRYPTION_CONFIG']
|
34
|
+
config_file =
|
35
|
+
if env_var
|
36
|
+
Pathname.new(File.expand_path(env_var))
|
36
37
|
else
|
37
38
|
Rails.root.join('config', 'symmetric-encryption.yml')
|
38
39
|
end
|
40
|
+
|
39
41
|
if config_file.file?
|
40
42
|
begin
|
41
43
|
::SymmetricEncryption::Config.load!(file_name: config_file, env: ENV['SYMMETRIC_ENCRYPTION_ENV'] || Rails.env)
|
@@ -45,10 +47,8 @@ module SymmetricEncryption #:nodoc:
|
|
45
47
|
puts "To generate a new config file and key files: symmetric-encryption --generate --app-name #{app_name}\n\n"
|
46
48
|
raise(exc)
|
47
49
|
end
|
48
|
-
else
|
49
|
-
puts "\nSymmetric Encryption config not found."
|
50
|
-
puts "To generate a new config file and key files: symmetric-encryption --generate --app-name #{app_name}\n\n"
|
51
50
|
end
|
51
|
+
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
@@ -8,11 +8,6 @@ require 'erb'
|
|
8
8
|
# The symmetric key is protected using the private key below and must
|
9
9
|
# be distributed separately from the application
|
10
10
|
module SymmetricEncryption
|
11
|
-
# Defaults
|
12
|
-
@@cipher = nil
|
13
|
-
@@secondary_ciphers = []
|
14
|
-
@@select_cipher = nil
|
15
|
-
|
16
11
|
# List of types supported when encrypting or decrypting data
|
17
12
|
#
|
18
13
|
# Each type maps to the built-in Ruby types as follows:
|
@@ -39,7 +34,7 @@ module SymmetricEncryption
|
|
39
34
|
def self.cipher=(cipher)
|
40
35
|
raise(ArgumentError, 'Cipher must respond to :encrypt and :decrypt') unless cipher.nil? || (cipher.respond_to?(:encrypt) && cipher.respond_to?(:decrypt))
|
41
36
|
|
42
|
-
|
37
|
+
@cipher = cipher
|
43
38
|
end
|
44
39
|
|
45
40
|
# Returns the Primary Symmetric Cipher being used
|
@@ -54,14 +49,14 @@ module SymmetricEncryption
|
|
54
49
|
)
|
55
50
|
end
|
56
51
|
|
57
|
-
return
|
52
|
+
return @cipher if version.nil? || (@cipher.version == version)
|
58
53
|
|
59
|
-
secondary_ciphers.find { |c| c.version == version } || (
|
54
|
+
secondary_ciphers.find { |c| c.version == version } || (@cipher if version.zero?)
|
60
55
|
end
|
61
56
|
|
62
57
|
# Returns whether a primary cipher has been set
|
63
58
|
def self.cipher?
|
64
|
-
|
59
|
+
!@cipher.nil?
|
65
60
|
end
|
66
61
|
|
67
62
|
# Set the Secondary Symmetric Ciphers Array to be used
|
@@ -71,12 +66,23 @@ module SymmetricEncryption
|
|
71
66
|
secondary_ciphers.each do |cipher|
|
72
67
|
raise(ArgumentError, 'secondary_ciphers can only consist of SymmetricEncryption::Ciphers') unless cipher.respond_to?(:encrypt) && cipher.respond_to?(:decrypt)
|
73
68
|
end
|
74
|
-
|
69
|
+
@secondary_ciphers = secondary_ciphers
|
75
70
|
end
|
76
71
|
|
77
72
|
# Returns the Primary Symmetric Cipher being used
|
78
73
|
def self.secondary_ciphers
|
79
|
-
|
74
|
+
@secondary_ciphers
|
75
|
+
end
|
76
|
+
|
77
|
+
# Whether to randomize the iv by default.
|
78
|
+
# true: Generate a new random IV by default. [HIGHLY RECOMMENDED]
|
79
|
+
# false: Do not generate a new random IV by default.
|
80
|
+
def self.randomize_iv?
|
81
|
+
@randomize_iv
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.randomize_iv=(randomize_iv)
|
85
|
+
@randomize_iv = randomize_iv
|
80
86
|
end
|
81
87
|
|
82
88
|
# Decrypt supplied string.
|
@@ -133,9 +139,9 @@ module SymmetricEncryption
|
|
133
139
|
if version
|
134
140
|
# Supplied version takes preference
|
135
141
|
cipher(version)
|
136
|
-
elsif
|
142
|
+
elsif @select_cipher
|
137
143
|
# Use cipher_selector if present to decide which cipher to use
|
138
|
-
|
144
|
+
@select_cipher.call(str, decoded)
|
139
145
|
else
|
140
146
|
# Global cipher
|
141
147
|
cipher
|
@@ -172,10 +178,12 @@ module SymmetricEncryption
|
|
172
178
|
# to convert it to a string
|
173
179
|
#
|
174
180
|
# random_iv [true|false]
|
175
|
-
#
|
176
|
-
#
|
177
|
-
#
|
178
|
-
#
|
181
|
+
# Mandatory unless `SymmetricEncryption.randomize_iv = true` has been called.
|
182
|
+
#
|
183
|
+
# Whether the encrypted value should use a random IV every time the field is encrypted.
|
184
|
+
# It is recommended to set this to true where possible.
|
185
|
+
#
|
186
|
+
# If the encrypted value could be used as part of a SQL where clause, or as part
|
179
187
|
# of any lookup, then it must be false.
|
180
188
|
# Setting random_iv to true will result in a different encrypted output for
|
181
189
|
# the same input string.
|
@@ -203,7 +211,7 @@ module SymmetricEncryption
|
|
203
211
|
# Note: If type is set to something other than :string, it's expected that
|
204
212
|
# the coercible gem is available in the path.
|
205
213
|
# Default: :string
|
206
|
-
def self.encrypt(str, random_iv:
|
214
|
+
def self.encrypt(str, random_iv: SymmetricEncryption.randomize_iv?, compress: false, type: :string, header: cipher.always_add_header)
|
207
215
|
return str if str.nil? || (str == '')
|
208
216
|
|
209
217
|
# Encrypt and then encode the supplied string
|
@@ -265,7 +273,7 @@ module SymmetricEncryption
|
|
265
273
|
# encoded_str.end_with?("\n") ? SymmetricEncryption.cipher(0) : SymmetricEncryption.cipher
|
266
274
|
# end
|
267
275
|
def self.select_cipher(&block)
|
268
|
-
|
276
|
+
@select_cipher = block || nil
|
269
277
|
end
|
270
278
|
|
271
279
|
# Load the Encryption Configuration from a YAML file
|
@@ -288,4 +296,10 @@ module SymmetricEncryption
|
|
288
296
|
|
289
297
|
BINARY_ENCODING = Encoding.find('binary')
|
290
298
|
UTF8_ENCODING = Encoding.find('UTF-8')
|
299
|
+
|
300
|
+
# Defaults
|
301
|
+
@cipher = nil
|
302
|
+
@secondary_ciphers = []
|
303
|
+
@select_cipher = nil
|
304
|
+
@random_iv = false
|
291
305
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: symmetric-encryption
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Reid Morrison
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-05-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: coercible
|
@@ -38,6 +38,8 @@ files:
|
|
38
38
|
- bin/symmetric-encryption
|
39
39
|
- lib/symmetric-encryption.rb
|
40
40
|
- lib/symmetric_encryption.rb
|
41
|
+
- lib/symmetric_encryption/active_record/attr_encrypted.rb
|
42
|
+
- lib/symmetric_encryption/active_record/encrypted_attribute.rb
|
41
43
|
- lib/symmetric_encryption/cipher.rb
|
42
44
|
- lib/symmetric_encryption/cli.rb
|
43
45
|
- lib/symmetric_encryption/coerce.rb
|
@@ -56,7 +58,6 @@ files:
|
|
56
58
|
- lib/symmetric_encryption/keystore/heroku.rb
|
57
59
|
- lib/symmetric_encryption/keystore/memory.rb
|
58
60
|
- lib/symmetric_encryption/railtie.rb
|
59
|
-
- lib/symmetric_encryption/railties/attr_encrypted.rb
|
60
61
|
- lib/symmetric_encryption/railties/mongoid_encrypted.rb
|
61
62
|
- lib/symmetric_encryption/railties/symmetric_encryption_validator.rb
|
62
63
|
- lib/symmetric_encryption/reader.rb
|
@@ -86,7 +87,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
86
87
|
- !ruby/object:Gem::Version
|
87
88
|
version: '0'
|
88
89
|
requirements: []
|
89
|
-
rubygems_version: 3.0.
|
90
|
+
rubygems_version: 3.0.3
|
90
91
|
signing_key:
|
91
92
|
specification_version: 4
|
92
93
|
summary: Encrypt ActiveRecord and Mongoid attributes, files and passwords in configuration
|