symmetric-encryption 4.0.1 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
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