symmetric-encryption 4.0.1 → 4.1.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -7
  3. data/lib/symmetric_encryption/cipher.rb +11 -4
  4. data/lib/symmetric_encryption/cli.rb +39 -28
  5. data/lib/symmetric_encryption/config.rb +9 -6
  6. data/lib/symmetric_encryption/encoder.rb +6 -0
  7. data/lib/symmetric_encryption/extensions/mongoid/encrypted.rb +1 -0
  8. data/lib/symmetric_encryption/generator.rb +1 -1
  9. data/lib/symmetric_encryption/header.rb +7 -5
  10. data/lib/symmetric_encryption/key.rb +2 -62
  11. data/lib/symmetric_encryption/keystore/aws.rb +172 -0
  12. data/lib/symmetric_encryption/keystore/environment.rb +7 -30
  13. data/lib/symmetric_encryption/keystore/file.rb +8 -30
  14. data/lib/symmetric_encryption/keystore/heroku.rb +22 -0
  15. data/lib/symmetric_encryption/keystore/memory.rb +4 -3
  16. data/lib/symmetric_encryption/keystore.rb +151 -36
  17. data/lib/symmetric_encryption/railtie.rb +9 -4
  18. data/lib/symmetric_encryption/railties/symmetric_encryption_validator.rb +1 -0
  19. data/lib/symmetric_encryption/reader.rb +50 -58
  20. data/lib/symmetric_encryption/symmetric_encryption.rb +2 -1
  21. data/lib/symmetric_encryption/utils/aws.rb +141 -0
  22. data/lib/symmetric_encryption/utils/re_encrypt_files.rb +12 -5
  23. data/lib/symmetric_encryption/version.rb +1 -1
  24. data/lib/symmetric_encryption/writer.rb +33 -27
  25. data/lib/symmetric_encryption.rb +27 -6
  26. data/test/active_record_test.rb +25 -25
  27. data/test/cipher_test.rb +3 -3
  28. data/test/header_test.rb +1 -1
  29. data/test/key_test.rb +0 -157
  30. data/test/keystore/aws_test.rb +133 -0
  31. data/test/keystore/environment_test.rb +3 -51
  32. data/test/keystore/file_test.rb +13 -52
  33. data/test/keystore/heroku_test.rb +70 -0
  34. data/test/keystore_test.rb +200 -4
  35. data/test/mongoid_test.rb +15 -15
  36. data/test/reader_test.rb +28 -8
  37. data/test/symmetric_encryption_test.rb +2 -2
  38. data/test/test_db.sqlite3 +0 -0
  39. data/test/test_helper.rb +1 -0
  40. data/test/utils/aws_test.rb +74 -0
  41. data/test/writer_test.rb +48 -46
  42. metadata +29 -20
@@ -0,0 +1,141 @@
1
+ require 'base64'
2
+ require 'aws-sdk-kms'
3
+ module SymmetricEncryption
4
+ module Utils
5
+ # Wrap the AWS KMS client so that it automatically creates the Customer Master Key,
6
+ # if one does not already exist.
7
+ #
8
+ # Map OpenSSL cipher names to AWS KMS key specs.
9
+ class Aws
10
+ attr_reader :master_key_alias, :client
11
+
12
+ AWS_US_REGIONS = %w[us-east-1 us-east-2 us-west-1 us-west-2].freeze
13
+
14
+ # TODO: Map to OpenSSL ciphers
15
+ AWS_KEY_SPEC_MAP = {
16
+ 'aes-256-cbc' => 'AES_256',
17
+ 'aes-128-cbc' => 'AES_128'
18
+ }.freeze
19
+
20
+ # TODO: Move to Keystore::Aws
21
+ # Rotate the Customer Master key in each of the supplied regions.
22
+ # After the master key has been rotated, use `.write_key_files` to generate
23
+ # a new DEK and re-encrypt with the new CMK in each region.
24
+ # def self.rotate_master_key(master_key_alias:, cipher_name:, regions: AWS_US_REGIONS)
25
+ # Array(regions).collect do |region|
26
+ # key_manager = new(region: region, master_key_alias: master_key_alias, cipher_name: cipher_name)
27
+ # key_id = key_manager.create_master_key
28
+ # key_manager.create_alias(key_id)
29
+ # end
30
+ # end
31
+
32
+ def initialize(region:, master_key_alias:)
33
+ # Can region be read from environment?
34
+ # Region is required for filename / env var name
35
+ @client = ::Aws::KMS::Client.new(region: region)
36
+ @master_key_alias = master_key_alias
37
+ end
38
+
39
+ # Returns a new DEK encrypted using the CMK
40
+ def generate_encrypted_data_key(cipher_name)
41
+ auto_create_master_key do
42
+ client.generate_data_key_without_plaintext(key_id: master_key_alias, key_spec: key_spec(cipher_name)).ciphertext_blob
43
+ end
44
+ end
45
+
46
+ # Returns a new DEK in the clear
47
+ def generate_data_key(cipher_name)
48
+ auto_create_master_key do
49
+ client.generate_data_key(key_id: master_key_alias, key_spec: key_spec(cipher_name)).plaintext
50
+ end
51
+ end
52
+
53
+ # Decrypt data previously encrypted using the cmk
54
+ def decrypt(encrypted_data)
55
+ auto_create_master_key do
56
+ client.decrypt(ciphertext_blob: encrypted_data).plaintext
57
+ end
58
+ end
59
+
60
+ # Decrypt data previously encrypted using the cmk
61
+ def encrypt(data)
62
+ auto_create_master_key do
63
+ client.encrypt(key_id: master_key_alias, plaintext: data).ciphertext_blob
64
+ end
65
+ end
66
+
67
+ # Returns the AWS KMS key spec that matches the supplied OpenSSL cipher name
68
+ def key_spec(cipher_name)
69
+ key_spec = AWS_KEY_SPEC_MAP[cipher_name]
70
+ raise("OpenSSL Cipher: #{cipher_name} has not yet been mapped to an AWS key spec.") unless key_spec
71
+
72
+ key_spec
73
+ end
74
+
75
+ # Creates a new master key along with an alias that points to it.
76
+ # Returns [String] the new master key id that was created.
77
+ def create_master_key
78
+ key_id = create_new_master_key
79
+ create_alias(key_id)
80
+ key_id
81
+ end
82
+
83
+ # Deletes the current master key and its alias.
84
+ #
85
+ # retention_days: Number of days to keep the CMK before completely destroying it.
86
+ #
87
+ # NOTE:
88
+ # Use with caution, only intended for testing purposes !!!
89
+ def delete_master_key(retention_days: 30)
90
+ key_info = client.describe_key(key_id: master_key_alias)
91
+ ap key_info
92
+ resp = client.schedule_key_deletion(key_id: key_info.key_metadata.key_id, pending_window_in_days: retention_days)
93
+ ap client.delete_alias(alias_name: master_key_alias)
94
+ resp.deletion_date
95
+ rescue ::Aws::KMS::Errors::NotFoundException
96
+ nil
97
+ end
98
+
99
+ private
100
+
101
+ attr_reader :client
102
+
103
+ def whoami
104
+ @whoami ||= `whoami`.strip
105
+ rescue StandardError
106
+ @whoami = 'unknown'
107
+ end
108
+
109
+ # Creates a new Customer Master Key for Symmetric Encryption use.
110
+ def create_new_master_key
111
+ # TODO: Add error handling and retry
112
+
113
+ resp = client.create_key(
114
+ description: 'Symmetric Encryption for Ruby Customer Masker Key',
115
+ tags: [
116
+ {tag_key: 'CreatedAt', tag_value: Time.now.to_s},
117
+ {tag_key: 'CreatedBy', tag_value: whoami}
118
+ ]
119
+ )
120
+ resp.key_metadata.key_id
121
+ end
122
+
123
+ def create_alias(key_id)
124
+ # TODO: Add error handling and retry
125
+ # TODO: Move existing alias if any
126
+ client.create_alias(alias_name: master_key_alias, target_key_id: key_id)
127
+ end
128
+
129
+ def auto_create_master_key
130
+ attempt = 1
131
+ yield
132
+ rescue ::Aws::KMS::Errors::NotFoundException
133
+ raise if attempt >= 2
134
+
135
+ create_master_key
136
+ attempt += 1
137
+ retry
138
+ end
139
+ end
140
+ end
141
+ end
@@ -52,16 +52,24 @@ module SymmetricEncryption
52
52
  def re_encrypt_contents(file_name)
53
53
  return 0 if File.size(file_name) > 256 * 1024
54
54
 
55
+ lines = File.read(file_name)
56
+ hits, output_lines = re_encrypt_lines(lines)
57
+
58
+ File.open(file_name, 'wb') { |file| file.write(output_lines) } if hits.positive?
59
+ hits
60
+ end
61
+
62
+ # Replaces instances of encrypted data within lines of text with re-encrypted values
63
+ def re_encrypt_lines(lines)
55
64
  hits = 0
56
- lines = File.read(file_name)
57
65
  output_lines = ''
58
66
  r = regexp
59
67
  lines.each_line do |line|
60
68
  line.force_encoding(SymmetricEncryption::UTF8_ENCODING)
61
69
  output_lines <<
62
70
  if line.valid_encoding? && (result = line.match(r))
63
- encrypted = result[0]
64
- new_value = re_encrypt(encrypted)
71
+ encrypted = result[0]
72
+ new_value = re_encrypt(encrypted)
65
73
  if new_value != encrypted
66
74
  hits += 1
67
75
  line.gsub(encrypted, new_value)
@@ -72,8 +80,7 @@ module SymmetricEncryption
72
80
  line
73
81
  end
74
82
  end
75
- File.open(file_name, 'wb') { |file| file.write(output_lines) } if hits.positive?
76
- hits
83
+ [hits, output_lines]
77
84
  end
78
85
 
79
86
  # Re Encrypt an entire file
@@ -1,3 +1,3 @@
1
1
  module SymmetricEncryption
2
- VERSION = '4.0.1'.freeze
2
+ VERSION = '4.1.0'.freeze
3
3
  end
@@ -21,7 +21,7 @@ module SymmetricEncryption
21
21
  # compress: [true|false]
22
22
  # Uses Zlib to compress the data before it is encrypted and
23
23
  # written to the file/stream.
24
- # Default: false
24
+ # Default: true, unless the file_name extension indicates it is already compressed.
25
25
  #
26
26
  # Note: Compression occurs before encryption
27
27
  #
@@ -47,11 +47,16 @@ module SymmetricEncryption
47
47
  # ensure
48
48
  # csv.close if csv
49
49
  # end
50
- def self.open(file_name_or_stream, compress: false, **args)
51
- ios = file_name_or_stream.is_a?(String) ? ::File.open(file_name_or_stream, 'wb') : file_name_or_stream
50
+ def self.open(file_name_or_stream, compress: nil, **args)
51
+ if file_name_or_stream.is_a?(String)
52
+ file_name_or_stream = ::File.open(file_name_or_stream, 'wb')
53
+ compress = !(/\.(zip|gz|gzip|xls.|)\z/i === file_name_or_stream) if compress.nil?
54
+ else
55
+ compress = true if compress.nil?
56
+ end
52
57
 
53
58
  begin
54
- file = new(ios, compress: compress, **args)
59
+ file = new(file_name_or_stream, compress: compress, **args)
55
60
  file = Zlib::GzipWriter.new(file) if compress
56
61
  block_given? ? yield(file) : file
57
62
  ensure
@@ -64,7 +69,7 @@ module SymmetricEncryption
64
69
  # Notes:
65
70
  # * Do not use this method for writing large files.
66
71
  def self.write(file_name_or_stream, data, **args)
67
- self.open(file_name_or_stream, **args) { |f| f.write(data) }
72
+ Writer.open(file_name_or_stream, **args) { |f| f.write(data) }
68
73
  end
69
74
 
70
75
  # Encrypt an entire file.
@@ -82,22 +87,10 @@ module SymmetricEncryption
82
87
  # Whether to compress the target file prior to encryption.
83
88
  # Default: false
84
89
  #
85
- # block_size: [Integer]
86
- # Number of bytes to read into memory for each read.
87
- # For very large files using a larger block size is faster.
88
- # Default: 65535
89
- #
90
90
  # Notes:
91
91
  # * The file contents are streamed so that the entire file is _not_ loaded into memory.
92
- def self.encrypt(source:, target:, block_size: 65_535, **args)
93
- source_ios = source.is_a?(String) ? ::File.open(source, 'rb') : source
94
- bytes_written = 0
95
- self.open(target, **args) do |output_file|
96
- bytes_written += output_file.write(source_ios.read(block_size)) until source_ios.eof?
97
- end
98
- bytes_written
99
- ensure
100
- source_ios.close if source_ios&.respond_to?(:closed?) && !source_ios.closed?
92
+ def self.encrypt(source:, target:, **args)
93
+ Writer.open(target, **args) { |output_file| IO.copy_stream(source, output_file) }
101
94
  end
102
95
 
103
96
  # Encrypt data before writing to the supplied stream
@@ -149,6 +142,7 @@ module SymmetricEncryption
149
142
  # ensure that the encrypted stream is closed before the stream itself is closed.
150
143
  def close(close_child_stream = true)
151
144
  return if closed?
145
+
152
146
  if size.positive?
153
147
  final = @stream_cipher.final
154
148
  @ios.write(final) unless final.empty?
@@ -160,14 +154,26 @@ module SymmetricEncryption
160
154
  # Write to the IO Stream as encrypted data.
161
155
  #
162
156
  # Returns [Integer] the number of bytes written.
163
- def write(data)
164
- return unless data
165
-
166
- bytes = data.to_s
167
- @size += bytes.size
168
- partial = @stream_cipher.update(bytes)
169
- @ios.write(partial) unless partial.empty?
170
- data.length
157
+ if defined?(JRuby)
158
+ def write(data)
159
+ return unless data
160
+
161
+ bytes = data.to_s
162
+ @size += bytes.size
163
+ partial = @stream_cipher.update(bytes)
164
+ @ios.write(partial) unless partial.empty?
165
+ data.length
166
+ end
167
+ else
168
+ def write(data)
169
+ return unless data
170
+
171
+ bytes = data.to_s
172
+ @size += bytes.size
173
+ partial = @stream_cipher.update(bytes, @cipher_buffer ||= ''.b)
174
+ @ios.write(partial) unless partial.empty?
175
+ data.length
176
+ end
171
177
  end
172
178
 
173
179
  # Write to the IO Stream as encrypted data.
@@ -22,19 +22,40 @@ module SymmetricEncryption
22
22
  autoload :CLI, 'symmetric_encryption/cli'
23
23
  autoload :Keystore, 'symmetric_encryption/keystore'
24
24
  module Utils
25
- autoload :Generate, 'symmetric_encryption/utils/generate'
25
+ autoload :Aws, 'symmetric_encryption/utils/aws'
26
26
  autoload :ReEncryptFiles, 'symmetric_encryption/utils/re_encrypt_files'
27
27
  end
28
28
  end
29
29
  # @formatter:on
30
30
 
31
31
  # Add support for other libraries only if they have already been loaded
32
- require 'symmetric_encryption/railtie' if defined?(Rails)
33
- if defined?(ActiveRecord::Base) && !defined?(AttrEncrypted::Version)
34
- require 'symmetric_encryption/extensions/active_record/base'
32
+
33
+ begin
34
+ require 'rails/railtie'
35
+ require 'symmetric_encryption/railtie' if defined?(Rails)
36
+ rescue LoadError
35
37
  end
36
- require 'symmetric_encryption/railties/symmetric_encryption_validator' if defined?(ActiveModel)
37
- require 'symmetric_encryption/extensions/mongoid/encrypted' if defined?(Mongoid)
38
+
39
+ begin
40
+ require 'active_record'
41
+ if defined?(ActiveRecord::Base) && !defined?(AttrEncrypted::Version)
42
+ require 'symmetric_encryption/extensions/active_record/base'
43
+ end
44
+ rescue LoadError
45
+ end
46
+
47
+ begin
48
+ require 'active_model'
49
+ require 'symmetric_encryption/railties/symmetric_encryption_validator' if defined?(ActiveModel)
50
+ rescue LoadError
51
+ end
52
+
53
+ begin
54
+ require 'mongoid'
55
+ require 'symmetric_encryption/extensions/mongoid/encrypted' if defined?(Mongoid)
56
+ rescue LoadError
57
+ end
58
+
38
59
  if defined?(MongoMapper)
39
60
  warn 'MongoMapper support is deprecated. Upgrade to Mongoid.'
40
61
  require 'symmetric_encryption/extensions/mongo_mapper/plugins/encrypted_key'
@@ -119,26 +119,26 @@ class ActiveRecordTest < Minitest::Test
119
119
  let :user do
120
120
  User.new(
121
121
  # Encrypted Attribute
122
- bank_account_number: bank_account_number,
122
+ bank_account_number: bank_account_number,
123
123
  # Encrypted Attribute
124
124
  social_security_number: social_security_number,
125
125
  name: person_name,
126
126
  # data type specific fields
127
- string_value: STRING_VALUE,
128
- long_string_value: LONG_STRING_VALUE,
129
- binary_string_value: BINARY_STRING_VALUE,
130
- integer_value: INTEGER_VALUE,
131
- float_value: FLOAT_VALUE,
132
- decimal_value: DECIMAL_VALUE,
133
- datetime_value: DATETIME_VALUE,
134
- time_value: TIME_VALUE,
135
- date_value: DATE_VALUE,
136
- true_value: true,
137
- false_value: false,
138
- data_yaml: hash_data.dup,
139
- data_json: hash_data.dup,
140
- text: 'hello',
141
- number: '21'
127
+ string_value: STRING_VALUE,
128
+ long_string_value: LONG_STRING_VALUE,
129
+ binary_string_value: BINARY_STRING_VALUE,
130
+ integer_value: INTEGER_VALUE,
131
+ float_value: FLOAT_VALUE,
132
+ decimal_value: DECIMAL_VALUE,
133
+ datetime_value: DATETIME_VALUE,
134
+ time_value: TIME_VALUE,
135
+ date_value: DATE_VALUE,
136
+ true_value: true,
137
+ false_value: false,
138
+ data_yaml: hash_data.dup,
139
+ data_json: hash_data.dup,
140
+ text: 'hello',
141
+ number: '21'
142
142
  )
143
143
  end
144
144
 
@@ -167,17 +167,17 @@ class ActiveRecordTest < Minitest::Test
167
167
  describe ':random_iv' do
168
168
  it 'false' do
169
169
  user.social_security_number = social_security_number
170
- assert first_value = user.social_security_number
170
+ assert first_value = user.social_security_number
171
171
  # Assign the same value
172
172
  user.social_security_number = social_security_number
173
173
  assert_equal first_value, user.social_security_number
174
174
  end
175
175
 
176
176
  it 'true' do
177
- user.string_value = STRING_VALUE
177
+ user.string_value = STRING_VALUE
178
178
  assert first_value = user.encrypted_string_value
179
- user.string_value = 'blah'
180
- user.string_value = STRING_VALUE
179
+ user.string_value = 'blah'
180
+ user.string_value = STRING_VALUE
181
181
  refute_equal first_value, user.encrypted_string_value
182
182
  end
183
183
 
@@ -200,7 +200,7 @@ class ActiveRecordTest < Minitest::Test
200
200
 
201
201
  it 'does not change when equal' do
202
202
  user.save!
203
- before = user.encrypted_string_value
203
+ before = user.encrypted_string_value
204
204
  user.string_value = STRING_VALUE
205
205
  refute user.string_value_changed?
206
206
  assert_equal before, user.encrypted_string_value
@@ -405,7 +405,7 @@ class ActiveRecordTest < Minitest::Test
405
405
 
406
406
  describe '#reload' do
407
407
  it 'reverts changes' do
408
- new_bank_account_number = '444444444'
408
+ new_bank_account_number = '444444444'
409
409
  user.bank_account_number = new_bank_account_number
410
410
  assert_equal new_bank_account_number, user.bank_account_number
411
411
 
@@ -416,8 +416,8 @@ class ActiveRecordTest < Minitest::Test
416
416
  end
417
417
 
418
418
  it 'reverts changes to encrypted field' do
419
- new_bank_account_number = '111111111'
420
- new_encrypted_bank_account_number = SymmetricEncryption.encrypt(new_bank_account_number)
419
+ new_bank_account_number = '111111111'
420
+ new_encrypted_bank_account_number = SymmetricEncryption.encrypt(new_bank_account_number)
421
421
  user.encrypted_bank_account_number = new_encrypted_bank_account_number
422
422
  assert_equal new_encrypted_bank_account_number, user.encrypted_bank_account_number
423
423
  assert_equal new_bank_account_number, user.bank_account_number
@@ -591,7 +591,7 @@ class ActiveRecordTest < Minitest::Test
591
591
  UniqueUser.destroy_all
592
592
  @email = 'whatever@not-unique.com'
593
593
  @username = 'gibby007'
594
- user = UniqueUser.create!(email: @email)
594
+ user = UniqueUser.create!(email: @email)
595
595
  @email_user = UniqueUser.create!(username: @username)
596
596
  end
597
597
 
data/test/cipher_test.rb CHANGED
@@ -93,7 +93,7 @@ class CipherTest < Minitest::Test
93
93
  always_add_header: always_add_header
94
94
  )
95
95
 
96
- h = @encrypted_values[cipher_name][encoding] if @encrypted_values[cipher_name]
96
+ h = @encrypted_values[cipher_name][encoding] if @encrypted_values[cipher_name]
97
97
  skip "Add @encrypted_values for cipher_name: #{cipher_name} and encoding: #{encoding}, value: #{@cipher.encrypt(@social_security_number).inspect}" unless h
98
98
  @social_security_number_encrypted = h[always_add_header ? :header : :no_header]
99
99
 
@@ -150,7 +150,7 @@ class CipherTest < Minitest::Test
150
150
 
151
151
  describe 'with configuration' do
152
152
  before do
153
- @cipher = SymmetricEncryption::Cipher.new(
153
+ @cipher = SymmetricEncryption::Cipher.new(
154
154
  key: '1234567890ABCDEF',
155
155
  iv: '1234567890ABCDEF',
156
156
  cipher_name: 'aes-128-cbc',
@@ -181,7 +181,7 @@ class CipherTest < Minitest::Test
181
181
  key.key,
182
182
  key.cipher_name
183
183
  )
184
- header = SymmetricEncryption::Header.new
184
+ header = SymmetricEncryption::Header.new
185
185
  header.parse(binary_header)
186
186
  assert_equal true, header.compressed?
187
187
  assert random_cipher = SymmetricEncryption::Cipher.new(iv: key.iv, key: key.key, cipher_name: key.cipher_name)
data/test/header_test.rb CHANGED
@@ -179,7 +179,7 @@ class CipherTest < Minitest::Test
179
179
  end
180
180
 
181
181
  it 'encrypted string' do
182
- header = SymmetricEncryption::Header.new
182
+ header = SymmetricEncryption::Header.new
183
183
  assert remainder = header.parse!(binary_encrypted_value)
184
184
  assert_equal SymmetricEncryption.cipher.version, header.version
185
185
  refute header.compressed?
data/test/key_test.rb CHANGED
@@ -2,15 +2,6 @@ require_relative 'test_helper'
2
2
 
3
3
  class KeyTest < Minitest::Test
4
4
  describe SymmetricEncryption::Key do
5
- before do
6
- Dir.mkdir('tmp') unless Dir.exist?('tmp')
7
- end
8
-
9
- after do
10
- # Cleanup generated encryption key files.
11
- `rm tmp/dek_tester* 2> /dev/null`
12
- end
13
-
14
5
  let :random_key do
15
6
  SymmetricEncryption::Key.new
16
7
  end
@@ -27,30 +18,6 @@ class KeyTest < Minitest::Test
27
18
  SymmetricEncryption::Key.new(key: stored_key, iv: stored_iv)
28
19
  end
29
20
 
30
- let :stored_key2 do
31
- 'ABCDEF1234567890ABCDEF1234567890'
32
- end
33
-
34
- let :stored_iv2 do
35
- '1234567890ABCDEF'
36
- end
37
-
38
- let :key2 do
39
- SymmetricEncryption::Key.new(key: stored_key2, iv: stored_iv2)
40
- end
41
-
42
- let :stored_key3 do
43
- 'ABCDEF0123456789ABCDEF0123456789'
44
- end
45
-
46
- let :stored_iv3 do
47
- '0123456789ABCDEF'
48
- end
49
-
50
- let :key3 do
51
- SymmetricEncryption::Key.new(key: stored_key3, iv: stored_iv3)
52
- end
53
-
54
21
  let :ssn do
55
22
  '987654321'
56
23
  end
@@ -110,129 +77,5 @@ class KeyTest < Minitest::Test
110
77
  assert_equal stored_iv, key.iv
111
78
  end
112
79
  end
113
-
114
- describe '.from_config' do
115
- let :config do
116
- {key: stored_key, iv: stored_iv}
117
- end
118
-
119
- let :config_key do
120
- SymmetricEncryption::Key.from_config(config)
121
- end
122
-
123
- let :dek_file_name do
124
- 'tmp/dek_tester_dek.encrypted_key'
125
- end
126
-
127
- describe 'key' do
128
- it 'key' do
129
- assert_equal stored_key, config_key.key
130
- end
131
-
132
- it 'iv' do
133
- assert_equal stored_iv, config_key.iv
134
- end
135
-
136
- it 'cipher_name' do
137
- assert_equal 'aes-256-cbc', config_key.cipher_name
138
- end
139
- end
140
-
141
- describe 'encrypted_key' do
142
- let :config do
143
- {encrypted_key: key2.encrypt(stored_key), iv: stored_iv, key_encrypting_key: {key: stored_key2, iv: stored_iv2}}
144
- end
145
-
146
- it 'key' do
147
- assert_equal stored_key, config_key.key
148
- end
149
-
150
- it 'iv' do
151
- assert_equal stored_iv, config_key.iv
152
- end
153
-
154
- it 'cipher_name' do
155
- assert_equal 'aes-256-cbc', config_key.cipher_name
156
- end
157
- end
158
-
159
- describe 'key_filename' do
160
- let :config do
161
- File.open(dek_file_name, 'wb') { |f| f.write(key2.encrypt(stored_key)) }
162
- {key_filename: dek_file_name, iv: stored_iv, key_encrypting_key: {key: stored_key2, iv: stored_iv2}}
163
- end
164
-
165
- it 'key' do
166
- assert_equal stored_key, config_key.key
167
- end
168
-
169
- it 'iv' do
170
- assert_equal stored_iv, config_key.iv
171
- end
172
-
173
- it 'cipher_name' do
174
- assert_equal 'aes-256-cbc', config_key.cipher_name
175
- end
176
- end
177
-
178
- describe 'key_env_var' do
179
- let :env_var do
180
- 'TEST_KEY'
181
- end
182
-
183
- let :config do
184
- ENV[env_var] = ::Base64.encode64(key2.encrypt(stored_key))
185
- {key_env_var: env_var, iv: stored_iv, key_encrypting_key: {key: stored_key2, iv: stored_iv2}}
186
- end
187
-
188
- it 'key' do
189
- assert_equal stored_key, config_key.key
190
- end
191
-
192
- it 'iv' do
193
- assert_equal stored_iv, config_key.iv
194
- end
195
-
196
- it 'cipher_name' do
197
- assert_equal 'aes-256-cbc', config_key.cipher_name
198
- end
199
- end
200
-
201
- describe 'file store with kekek' do
202
- let :kekek_file_name do
203
- 'tmp/tester_kekek.key'
204
- end
205
-
206
- let :config do
207
- File.open(dek_file_name, 'wb') { |f| f.write(key2.encrypt(stored_key)) }
208
- encrypted_key = key3.encrypt(stored_key2)
209
- File.open(kekek_file_name, 'wb') { |f| f.write(stored_key3) }
210
- {
211
- key_filename: dek_file_name,
212
- iv: stored_iv,
213
- key_encrypting_key: {
214
- encrypted_key: encrypted_key,
215
- iv: stored_iv2,
216
- key_encrypting_key: {
217
- key_filename: kekek_file_name,
218
- iv: stored_iv3
219
- }
220
- }
221
- }
222
- end
223
-
224
- it 'key' do
225
- assert_equal stored_key, config_key.key
226
- end
227
-
228
- it 'iv' do
229
- assert_equal stored_iv, config_key.iv
230
- end
231
-
232
- it 'cipher_name' do
233
- assert_equal 'aes-256-cbc', config_key.cipher_name
234
- end
235
- end
236
- end
237
80
  end
238
81
  end