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.
- checksums.yaml +4 -4
- data/README.md +0 -7
- data/lib/symmetric_encryption/cipher.rb +11 -4
- data/lib/symmetric_encryption/cli.rb +39 -28
- data/lib/symmetric_encryption/config.rb +9 -6
- data/lib/symmetric_encryption/encoder.rb +6 -0
- data/lib/symmetric_encryption/extensions/mongoid/encrypted.rb +1 -0
- data/lib/symmetric_encryption/generator.rb +1 -1
- data/lib/symmetric_encryption/header.rb +7 -5
- data/lib/symmetric_encryption/key.rb +2 -62
- data/lib/symmetric_encryption/keystore/aws.rb +172 -0
- data/lib/symmetric_encryption/keystore/environment.rb +7 -30
- data/lib/symmetric_encryption/keystore/file.rb +8 -30
- data/lib/symmetric_encryption/keystore/heroku.rb +22 -0
- data/lib/symmetric_encryption/keystore/memory.rb +4 -3
- data/lib/symmetric_encryption/keystore.rb +151 -36
- data/lib/symmetric_encryption/railtie.rb +9 -4
- data/lib/symmetric_encryption/railties/symmetric_encryption_validator.rb +1 -0
- data/lib/symmetric_encryption/reader.rb +50 -58
- data/lib/symmetric_encryption/symmetric_encryption.rb +2 -1
- data/lib/symmetric_encryption/utils/aws.rb +141 -0
- data/lib/symmetric_encryption/utils/re_encrypt_files.rb +12 -5
- data/lib/symmetric_encryption/version.rb +1 -1
- data/lib/symmetric_encryption/writer.rb +33 -27
- data/lib/symmetric_encryption.rb +27 -6
- data/test/active_record_test.rb +25 -25
- data/test/cipher_test.rb +3 -3
- data/test/header_test.rb +1 -1
- data/test/key_test.rb +0 -157
- data/test/keystore/aws_test.rb +133 -0
- data/test/keystore/environment_test.rb +3 -51
- data/test/keystore/file_test.rb +13 -52
- data/test/keystore/heroku_test.rb +70 -0
- data/test/keystore_test.rb +200 -4
- data/test/mongoid_test.rb +15 -15
- data/test/reader_test.rb +28 -8
- data/test/symmetric_encryption_test.rb +2 -2
- data/test/test_db.sqlite3 +0 -0
- data/test/test_helper.rb +1 -0
- data/test/utils/aws_test.rb +74 -0
- data/test/writer_test.rb +48 -46
- 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
|
64
|
-
new_value
|
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
|
-
|
76
|
-
hits
|
83
|
+
[hits, output_lines]
|
77
84
|
end
|
78
85
|
|
79
86
|
# Re Encrypt an entire file
|
@@ -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:
|
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:
|
51
|
-
|
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(
|
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
|
-
|
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:,
|
93
|
-
|
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
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
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.
|
data/lib/symmetric_encryption.rb
CHANGED
@@ -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 :
|
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
|
-
|
33
|
-
|
34
|
-
require '
|
32
|
+
|
33
|
+
begin
|
34
|
+
require 'rails/railtie'
|
35
|
+
require 'symmetric_encryption/railtie' if defined?(Rails)
|
36
|
+
rescue LoadError
|
35
37
|
end
|
36
|
-
|
37
|
-
|
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'
|
data/test/active_record_test.rb
CHANGED
@@ -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:
|
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:
|
128
|
-
long_string_value:
|
129
|
-
binary_string_value:
|
130
|
-
integer_value:
|
131
|
-
float_value:
|
132
|
-
decimal_value:
|
133
|
-
datetime_value:
|
134
|
-
time_value:
|
135
|
-
date_value:
|
136
|
-
true_value:
|
137
|
-
false_value:
|
138
|
-
data_yaml:
|
139
|
-
data_json:
|
140
|
-
text:
|
141
|
-
number:
|
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
|
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
|
177
|
+
user.string_value = STRING_VALUE
|
178
178
|
assert first_value = user.encrypted_string_value
|
179
|
-
user.string_value
|
180
|
-
user.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
|
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
|
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
|
420
|
-
new_encrypted_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
|
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
|
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
|
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
|
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
|
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
|