symmetric-encryption 4.2.1 → 4.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 40e60b20cfaf40c1b3ad68fb05b12fd766886ac3d4527a02c8d456906e45b705
4
- data.tar.gz: 3c87cffcfc26fe8a057619b3559c3f93ff5a3951c219eb90deb1c2054ae4495f
3
+ metadata.gz: d5499f0c6e33fc5eee0a2295623edd3bf35a247e1a6263a3e93f2c4e57219f22
4
+ data.tar.gz: ea3495cf8f5fe6b388725cd424ed13dc8b982c4ad225e78c7056f8d0f0d70cab
5
5
  SHA512:
6
- metadata.gz: 479105df621736ea8ccaddc73129f4c6d9ebad8a6918a793044d9d3329f547e3a7cbd404719bcbd9918a5cedb0c18694f22173201e799ab70d3a8032a7a90ac6
7
- data.tar.gz: dd8fd1b290bc1e2e55311234e8a06660dbc6f0849382189bc9408432caa519f973a1cbb7835eb97805136699eaf357772531cb7dfe6dbe2a62c33b4600c141f5
6
+ metadata.gz: a8a920045c6b813bb55e8a518727ffdaf03b0b5857f5326d8b6003946d81fb162f28eea69617934622626de66cbfbeaf27b464c5d7baa21e07332e2c7098f7e4
7
+ data.tar.gz: bb2a832909e3a81b1e357a4ec650e7f1fd93e81ab08a0a0f3664b586bc0bf60f1a821c26831f456138e77a7a29575bc976890f608ac10461a51e5fd86dbd2699
@@ -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/railties/attr_encrypted'
13
+ require 'symmetric_encryption/active_record/attr_encrypted'
14
14
  require 'symmetric_encryption/railties/symmetric_encryption_validator'
15
15
 
16
- ActiveRecord::Base.include(SymmetricEncryption::Railties::AttrEncrypted)
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 Railties
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(*params)
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
- options = params.last.is_a?(Hash) ? params.pop.dup : {}
51
+ random_iv = true if random_iv.nil? && SymmetricEncryption.randomize_iv?
52
52
 
53
- params.each do |attribute|
54
- SymmetricEncryption::Generator.generate_decrypted_accessors(self, attribute, "encrypted_#{attribute}", options)
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 [Fixnum]
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: false, compress: false, header: always_add_header)
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: false, compress: false, header: always_add_header)
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 = Rails::Application.subclasses.first.parent.to_s.underscore
33
- config_file =
34
- if (env_var = ENV['SYMMETRIC_ENCRYPTION_CONFIG'])
35
- Pathname.new File.expand_path(env_var)
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
- @@cipher = cipher
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 @@cipher if version.nil? || (@@cipher.version == version)
52
+ return @cipher if version.nil? || (@cipher.version == version)
58
53
 
59
- secondary_ciphers.find { |c| c.version == version } || (@@cipher if version.zero?)
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
- !@@cipher.nil?
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
- @@secondary_ciphers = secondary_ciphers
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
- @@secondary_ciphers
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 @@select_cipher
142
+ elsif @select_cipher
137
143
  # Use cipher_selector if present to decide which cipher to use
138
- @@select_cipher.call(str, decoded)
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
- # Whether the encypted value should use a random IV every time the
176
- # field is encrypted.
177
- # It is recommended to set this to true where feasible. If the encrypted
178
- # value could be used as part of a SQL where clause, or as part
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: false, compress: false, type: :string, header: cipher.always_add_header)
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
- @@select_cipher = block || nil
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
@@ -1,3 +1,3 @@
1
1
  module SymmetricEncryption
2
- VERSION = '4.2.1'.freeze
2
+ VERSION = '4.3.0'.freeze
3
3
  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.2.1
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-04-04 00:00:00.000000000 Z
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.2
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