symmetric-encryption 4.1.1 → 4.1.2

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.
data/test/reader_test.rb DELETED
@@ -1,334 +0,0 @@
1
- require_relative 'test_helper'
2
- require 'stringio'
3
-
4
- # Unit Test for SymmetricEncrypted::ReaderStream
5
- #
6
- class ReaderTest < Minitest::Test
7
- describe SymmetricEncryption::Reader do
8
- before do
9
- @data = [
10
- "Hello World\n",
11
- "Keep this secret\n",
12
- 'And keep going even further and further...'
13
- ]
14
- @data_str = @data.inject('') { |sum, str| sum << str }
15
- @data_len = @data_str.length
16
- # Use Cipher 0 since it does not always include a header
17
- @cipher = SymmetricEncryption.cipher(0)
18
- @data_encrypted_without_header = @cipher.binary_encrypt(@data_str, header: false)
19
-
20
- header = SymmetricEncryption::Header.new(
21
- version: @cipher.version,
22
- iv: @cipher.iv,
23
- key: @cipher.send(:key),
24
- cipher_name: @cipher.cipher_name
25
- )
26
- @data_encrypted_with_header = @cipher.binary_encrypt(@data_str, header: header)
27
-
28
- # Verify regular decrypt can decrypt this string
29
- @cipher.binary_decrypt(@data_encrypted_without_header)
30
- @cipher.binary_decrypt(@data_encrypted_with_header)
31
- assert @data_encrypted_without_header != @data_encrypted_with_header
32
- end
33
-
34
- [true, false].each do |header|
35
- describe header do
36
- before do
37
- @data_encrypted = header ? @data_encrypted_with_header : @data_encrypted_without_header
38
- end
39
-
40
- it '#read()' do
41
- stream = StringIO.new(@data_encrypted)
42
- # Version 0 supplied if the file/stream does not have a header
43
- decrypted = SymmetricEncryption::Reader.open(stream, version: 0, &:read)
44
- assert_equal @data_str, decrypted
45
- end
46
-
47
- it '#read(size) followed by #read()' do
48
- stream = StringIO.new(@data_encrypted)
49
- # Version 0 supplied if the file/stream does not have a header
50
- decrypted = SymmetricEncryption::Reader.open(stream, version: 0) do |file|
51
- file.read(10)
52
- file.read
53
- end
54
- assert_equal @data_str[10..-1], decrypted
55
- end
56
-
57
- it '#each_line' do
58
- stream = StringIO.new(@data_encrypted)
59
- i = 0
60
- # Version 0 supplied if the file/stream does not have a header
61
- SymmetricEncryption::Reader.open(stream, version: 0) do |file|
62
- file.each_line do |line|
63
- assert_equal @data[i], line
64
- i += 1
65
- end
66
- end
67
- end
68
-
69
- it '#read(size)' do
70
- stream = StringIO.new(@data_encrypted)
71
- # Version 0 supplied if the file/stream does not have a header
72
- SymmetricEncryption::Reader.open(stream, version: 0) do |file|
73
- index = 0
74
- [0, 10, 5, 5000].each do |size|
75
- buf = file.read(size)
76
- if size.zero?
77
- assert_equal '', buf
78
- else
79
- assert_equal @data_str[index..index + size - 1], buf
80
- end
81
- index += size
82
- end
83
- end
84
- end
85
- end
86
- end
87
-
88
- [
89
- # No Header
90
- {header: false, random_key: false, random_iv: false, compress: false},
91
- # Default Header with random key and iv
92
- {},
93
- # Header with no compression ( default anyway )
94
- {compress: false},
95
- # Compress and use Random key, iv
96
- {compress: true},
97
- # Header but not random key or iv
98
- {random_key: false},
99
- # Random iv only
100
- {random_key: false, random_iv: true},
101
- # Random iv only with compression
102
- {random_iv: true, compress: true}
103
- ].each do |options|
104
-
105
- %i[data empty blank].each do |usecase|
106
- describe "read from #{usecase} file with options: #{options.inspect}" do
107
- before do
108
- case usecase
109
- when :data
110
- # Create encrypted file
111
- @eof = false
112
- @file_name = '_test'
113
- @header = (options[:header] != false)
114
- SymmetricEncryption::Writer.open(@file_name, options) do |file|
115
- @data.inject(0) { |sum, str| sum + file.write(str) }
116
- end
117
- when :empty
118
- @data_str = ''
119
- @eof = true
120
- @file_name = '_test_empty'
121
- @header = (options[:header] != false)
122
- SymmetricEncryption::Writer.open(@file_name, options) do |file|
123
- # Leave data portion empty
124
- end
125
- when :blank
126
- @data_str = ''
127
- @eof = true
128
- @file_name = File.join(File.dirname(__FILE__), 'config/empty.csv')
129
- @header = false
130
- assert_equal 0, File.size(@file_name)
131
- else
132
- raise "Unhandled usecase: #{usecase}"
133
- end
134
- @data_size = @data_str.length
135
- end
136
-
137
- after do
138
- File.delete(@file_name) if File.exist?(@file_name) && !@file_name.end_with?('empty.csv')
139
- end
140
-
141
- it '.empty?' do
142
- assert_equal @data_size.zero?, SymmetricEncryption::Reader.empty?(@file_name)
143
- assert_raises Errno::ENOENT do
144
- SymmetricEncryption::Reader.empty?('missing_file')
145
- end
146
- end
147
-
148
- it '.header_present?' do
149
- assert_equal @header, SymmetricEncryption::Reader.header_present?(@file_name)
150
- assert_raises Errno::ENOENT do
151
- SymmetricEncryption::Reader.header_present?('missing_file')
152
- end
153
- end
154
-
155
- it '.open return Zlib::GzipReader when compressed' do
156
- file = SymmetricEncryption::Reader.open(@file_name)
157
- # assert_equal (@header && (options[:compress]||false)), file.is_a?(Zlib::GzipReader)
158
- file.close
159
- end
160
-
161
- it '#read' do
162
- data = nil
163
- eof = nil
164
- result = SymmetricEncryption::Reader.open(@file_name) do |file|
165
- eof = file.eof?
166
- data = file.read
167
- end
168
- assert_equal @eof, eof
169
- assert_equal @data_str, data
170
- assert_equal @data_str, result
171
- end
172
-
173
- it '#read(size)' do
174
- file = SymmetricEncryption::Reader.open(@file_name)
175
- eof = file.eof?
176
- data = file.read(4096)
177
- file.close
178
-
179
- assert_equal @eof, eof
180
- if @data_size.positive?
181
- assert_equal @data_str, data
182
- else
183
- assert_nil data
184
- end
185
- end
186
-
187
- it '#read(size, outbuf)' do
188
- file = SymmetricEncryption::Reader.open(@file_name)
189
- # Not supported with compressed files
190
- if file.is_a?(SymmetricEncryption::Reader)
191
- eof = file.eof?
192
- output_buffer = 'buffer'
193
- data = file.read(4096, output_buffer)
194
- file.close
195
-
196
- assert_equal @eof, eof
197
- if @data_size.positive?
198
- assert_equal @data_str, data
199
- assert_equal data.object_id, output_buffer.object_id
200
- else
201
- assert_nil data
202
- assert_empty output_buffer
203
- end
204
- end
205
- end
206
-
207
- it '#each_line' do
208
- SymmetricEncryption::Reader.open(@file_name) do |file|
209
- i = 0
210
- file.each_line do |line|
211
- assert_equal @data[i], line
212
- i += 1
213
- end
214
- end
215
- end
216
-
217
- it '#rewind' do
218
- decrypted = SymmetricEncryption::Reader.open(@file_name) do |file|
219
- file.read
220
- file.rewind
221
- file.read
222
- end
223
- assert_equal @data_str, decrypted
224
- end
225
-
226
- it '#gets(nil,size)' do
227
- file = SymmetricEncryption::Reader.open(@file_name)
228
- eof = file.eof?
229
- data = file.gets(nil, 4096)
230
- file.close
231
-
232
- assert_equal @eof, eof
233
- if @data_size.positive?
234
- assert_equal @data_str, data
235
- elsif defined?(JRuby)
236
- # On JRuby Zlib::GzipReader.new(file) returns '' instead of nil on an empty file
237
- assert data.blank?
238
- else
239
- assert_nil data
240
- end
241
- end
242
-
243
- it '#gets(delim)' do
244
- SymmetricEncryption::Reader.open(@file_name) do |file|
245
- i = 0
246
- while (line = file.gets("\n"))
247
- assert_equal @data[i], line
248
- i += 1
249
- end
250
- assert_equal (@data_size.positive? ? 3 : 0), i
251
- end
252
- end
253
-
254
- it '#gets(delim,size)' do
255
- SymmetricEncryption::Reader.open(@file_name) do |file|
256
- i = 0
257
- i += 1 while file.gets("\n", 128)
258
- assert_equal (@data_size.positive? ? 3 : 0), i
259
- end
260
- end
261
- end
262
- end
263
- end
264
-
265
- describe 'reading from files with previous keys' do
266
- before do
267
- @file_name = '_test'
268
- # Create encrypted file with old encryption key
269
- SymmetricEncryption::Writer.open(@file_name, version: 0) do |file|
270
- @data.inject(0) { |sum, str| sum + file.write(str) }
271
- end
272
- end
273
-
274
- after do
275
- File.delete(@file_name) if File.exist?(@file_name)
276
- end
277
-
278
- it 'decrypt from file in a single read' do
279
- decrypted = SymmetricEncryption::Reader.open(@file_name, &:read)
280
- assert_equal @data_str, decrypted
281
- end
282
-
283
- it 'decrypt from file a line at a time' do
284
- SymmetricEncryption::Reader.open(@file_name) do |file|
285
- i = 0
286
- file.each_line do |line|
287
- assert_equal @data[i], line
288
- i += 1
289
- end
290
- end
291
- end
292
-
293
- it 'support rewind' do
294
- decrypted = SymmetricEncryption::Reader.open(@file_name) do |file|
295
- file.read
296
- file.rewind
297
- file.read
298
- end
299
- assert_equal @data_str, decrypted
300
- end
301
- end
302
-
303
- describe 'reading from files with previous keys without a header' do
304
- before do
305
- @file_name = '_test'
306
- # Create encrypted file with old encryption key
307
- SymmetricEncryption::Writer.open(@file_name, version: 0, header: false, random_key: false, random_iv: false, compress: false) do |file|
308
- @data.inject(0) { |sum, str| sum + file.write(str) }
309
- end
310
- end
311
-
312
- after do
313
- begin
314
- File.delete(@file_name) if File.exist?(@file_name)
315
- rescue Errno::EACCES
316
- # Required for Windows
317
- nil
318
- end
319
- end
320
-
321
- it 'decrypt from file in a single read' do
322
- decrypted = SymmetricEncryption::Reader.open(@file_name, version: 0, &:read)
323
- assert_equal @data_str, decrypted
324
- end
325
-
326
- it 'decrypt from file in a single read with different version' do
327
- # Should fail since file was encrypted using version 0 key
328
- assert_raises OpenSSL::Cipher::CipherError do
329
- SymmetricEncryption::Reader.read(@file_name, version: 1)
330
- end
331
- end
332
- end
333
- end
334
- end
@@ -1,239 +0,0 @@
1
- require_relative 'test_helper'
2
-
3
- # Unit Test for SymmetricEncryption
4
- #
5
- class SymmetricEncryptionTest < Minitest::Test
6
- describe 'SymmetricEncryption' do
7
- describe 'configuration' do
8
- before do
9
- config = SymmetricEncryption::Config.new(
10
- file_name: File.join(File.dirname(__FILE__), 'config', 'symmetric-encryption.yml'),
11
- env: 'test'
12
- )
13
- @ciphers = config.ciphers
14
-
15
- @cipher_v2, @cipher_v6, @cipher_v1, @cipher_v0 = @ciphers
16
- end
17
-
18
- it 'matches config file for first cipher' do
19
- cipher = SymmetricEncryption.cipher
20
- assert @cipher_v2.send(:key)
21
- assert @cipher_v2.send(:iv)
22
- assert @cipher_v2.version
23
- assert_equal @cipher_v2.cipher_name, cipher.cipher_name
24
- assert_equal @cipher_v2.version, cipher.version
25
- assert_equal false, SymmetricEncryption.secondary_ciphers.include?(cipher)
26
- end
27
-
28
- it 'match config file for v1 cipher' do
29
- cipher = SymmetricEncryption.cipher(2)
30
- assert @cipher_v2.cipher_name
31
- assert @cipher_v2.version
32
- assert_equal @cipher_v2.cipher_name, cipher.cipher_name
33
- assert_equal @cipher_v2.version, cipher.version
34
- assert_equal false, SymmetricEncryption.secondary_ciphers.include?(cipher)
35
- end
36
-
37
- it 'match config file for v0 cipher' do
38
- cipher = SymmetricEncryption.cipher(0)
39
- assert @cipher_v0.cipher_name
40
- assert @cipher_v0.version
41
- assert_equal @cipher_v0.cipher_name, cipher.cipher_name
42
- assert_equal @cipher_v0.version, cipher.version
43
- assert_equal true, SymmetricEncryption.secondary_ciphers.include?(cipher)
44
- end
45
- end
46
-
47
- %i[none base64 base64strict base16].each do |encoding|
48
- describe "encoding: #{encoding}" do
49
- before do
50
- @social_security_number = '987654321'
51
- @social_security_number_encrypted =
52
- case encoding
53
- when :base64
54
- "QEVuQwIAS+8X1NRrqdfEIQyFHVPuVA==\n"
55
- when :base64strict
56
- 'QEVuQwIAS+8X1NRrqdfEIQyFHVPuVA=='
57
- when :base16
58
- '40456e4302004bef17d4d46ba9d7c4210c851d53ee54'
59
- when :none
60
- "@EnC\x02\x00K\xEF\x17\xD4\xD4k\xA9\xD7\xC4!\f\x85\x1DS\xEET".force_encoding(Encoding.find('binary'))
61
- else
62
- raise "Add test for encoding: #{encoding}"
63
- end
64
- @non_utf8 = "\xc2".force_encoding('binary')
65
- @encoding = SymmetricEncryption.cipher.encoding
66
- SymmetricEncryption.cipher.encoding = encoding
67
- end
68
-
69
- after do
70
- SymmetricEncryption.cipher.encoding = @encoding
71
- end
72
-
73
- it 'encrypt simple string' do
74
- assert_equal @social_security_number_encrypted, SymmetricEncryption.encrypt(@social_security_number)
75
- end
76
-
77
- it 'decrypt string' do
78
- assert decrypted = SymmetricEncryption.decrypt(@social_security_number_encrypted)
79
- assert_equal @social_security_number, decrypted
80
- assert_equal Encoding.find('utf-8'), decrypted.encoding, decrypted
81
- end
82
-
83
- it 'return BINARY encoding for non-UTF-8 encrypted data' do
84
- assert_equal Encoding.find('binary'), @non_utf8.encoding
85
- assert_equal true, @non_utf8.valid_encoding?
86
- assert encrypted = SymmetricEncryption.encrypt(@non_utf8)
87
- assert decrypted = SymmetricEncryption.decrypt(encrypted)
88
- assert_equal true, decrypted.valid_encoding?
89
- assert_equal Encoding.find('binary'), decrypted.encoding, decrypted
90
- assert_equal @non_utf8, decrypted
91
- end
92
-
93
- it 'return nil when encrypting nil' do
94
- assert_nil SymmetricEncryption.encrypt(nil)
95
- end
96
-
97
- it "return '' when encrypting ''" do
98
- assert_equal '', SymmetricEncryption.encrypt('')
99
- end
100
-
101
- it 'return nil when decrypting nil' do
102
- assert_nil SymmetricEncryption.decrypt(nil)
103
- end
104
-
105
- it "return '' when decrypting ''" do
106
- assert_equal '', SymmetricEncryption.decrypt('')
107
- end
108
-
109
- it 'determine if string is encrypted' do
110
- if %i[base64strict base64].include?(encoding)
111
- assert SymmetricEncryption.encrypted?(@social_security_number_encrypted)
112
- refute SymmetricEncryption.encrypted?(@social_security_number)
113
-
114
- # Without a header it can only assume it is not encrypted
115
- refute SymmetricEncryption.encrypted?(SymmetricEncryption.encrypt(@social_security_number, header: false))
116
- end
117
- end
118
- end
119
- end
120
-
121
- describe 'using select_cipher' do
122
- before do
123
- @social_security_number = '987654321'
124
- # Encrypt data without a header and encode with base64 which has a trailing '\n'
125
- no_header = SymmetricEncryption.cipher(0).binary_encrypt(@social_security_number, header: false)
126
- @encrypted_0_ssn = SymmetricEncryption.cipher(0).encode(no_header)
127
-
128
- SymmetricEncryption.select_cipher do |encoded_str, _decoded_str|
129
- # Use cipher version 0 if the encoded string ends with "\n" otherwise
130
- # use the current default cipher
131
- encoded_str.end_with?("\n") ? SymmetricEncryption.cipher(0) : SymmetricEncryption.cipher
132
- end
133
- end
134
-
135
- after do
136
- # Clear out select_cipher
137
- SymmetricEncryption.select_cipher
138
- end
139
-
140
- it 'decrypt string without a header using an old cipher' do
141
- assert_equal @social_security_number, SymmetricEncryption.decrypt(@encrypted_0_ssn)
142
- end
143
- end
144
-
145
- describe 'without select_cipher' do
146
- before do
147
- @social_security_number = '987654321'
148
- # Encrypt data without a header and encode with base64 which has a trailing '\n'
149
- no_header = SymmetricEncryption.cipher(0).binary_encrypt(@social_security_number, header: false)
150
- assert @encrypted_0_ssn = SymmetricEncryption.cipher(0).encode(no_header)
151
- end
152
-
153
- it 'decrypt string without a header using an old cipher' do
154
- assert_raises OpenSSL::Cipher::CipherError do
155
- SymmetricEncryption.decrypt(@encrypted_0_ssn)
156
- end
157
- end
158
- end
159
-
160
- describe 'random iv' do
161
- before do
162
- @social_security_number = '987654321'
163
- end
164
-
165
- it 'encrypt and then decrypt using random iv' do
166
- # Encrypt with random iv
167
- assert encrypted = SymmetricEncryption.encrypt(@social_security_number, random_iv: true)
168
- assert_equal @social_security_number, SymmetricEncryption.decrypt(encrypted)
169
- end
170
-
171
- it 'encrypt and then decrypt using random iv with higher version' do
172
- # Encrypt with random iv
173
- assert encrypted = SymmetricEncryption.cipher(6).encrypt(@social_security_number, random_iv: true)
174
- assert_equal @social_security_number, SymmetricEncryption.decrypt(encrypted)
175
- end
176
-
177
- it 'encrypt and then decrypt using random iv with compression' do
178
- # Encrypt with random iv and compress
179
- assert encrypted = SymmetricEncryption.encrypt(@social_security_number, random_iv: true, compress: true)
180
- assert_equal @social_security_number, SymmetricEncryption.decrypt(encrypted)
181
- end
182
- end
183
-
184
- describe 'data types' do
185
- describe 'string' do
186
- before do
187
- @social_security_number = '987654321'
188
- end
189
-
190
- it 'encrypt and decrypt value to and from a string' do
191
- assert encrypted = SymmetricEncryption.encrypt(@social_security_number, type: :string)
192
- assert_equal @social_security_number, SymmetricEncryption.decrypt(encrypted, type: :string)
193
- end
194
-
195
- it 'retains empty' do
196
- encrypted = SymmetricEncryption.encrypt('', type: :string)
197
- assert_equal '', encrypted
198
- assert_equal '', SymmetricEncryption.decrypt(encrypted, type: :string)
199
- end
200
-
201
- it 'retains nil' do
202
- assert_nil encrypted = SymmetricEncryption.encrypt(nil, type: :string)
203
- assert_nil SymmetricEncryption.decrypt(encrypted, type: :string)
204
- end
205
- end
206
-
207
- {
208
- integer: 21,
209
- float: 2.5,
210
- decimal: BigDecimal('12.58'),
211
- datetime: DateTime.new(2001, 11, 26, 20, 55, 54, '-5'),
212
- time: Time.new(2013, 1, 1, 22, 30, 0, '-04:00'),
213
- date: Date.new(1927, 4, 1),
214
- boolean: true,
215
- yaml: {a: :b},
216
- json: {'a' => 'b'}
217
- }.each_pair do |type, value|
218
- describe type.to_s do
219
- it 'encrypt and decrypt' do
220
- assert encrypted = SymmetricEncryption.encrypt(value, type: type)
221
- assert_equal value, SymmetricEncryption.decrypt(encrypted, type: type)
222
- end
223
-
224
- it 'retains nil' do
225
- assert_nil encrypted = SymmetricEncryption.encrypt(nil, type: type)
226
- assert_nil SymmetricEncryption.decrypt(encrypted, type: type)
227
- end
228
- end
229
- end
230
-
231
- describe 'boolean false' do
232
- it 'encrypt and decrypt' do
233
- assert encrypted = SymmetricEncryption.encrypt(false, type: :boolean)
234
- assert_equal false, SymmetricEncryption.decrypt(encrypted, type: :boolean)
235
- end
236
- end
237
- end
238
- end
239
- end
data/test/test_db.sqlite3 DELETED
Binary file
data/test/test_helper.rb DELETED
@@ -1,12 +0,0 @@
1
- $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
2
-
3
- require 'yaml'
4
- require 'minitest/autorun'
5
- require 'minitest/stub_any_instance'
6
- require 'awesome_print'
7
- require 'active_record'
8
- require 'symmetric-encryption'
9
- require 'fileutils'
10
-
11
- # Load Symmetric Encryption keys
12
- SymmetricEncryption.load!(File.join(File.dirname(__FILE__), 'config', 'symmetric-encryption.yml'), 'test')
@@ -1,74 +0,0 @@
1
- require_relative '../test_helper'
2
- require 'stringio'
3
-
4
- module SymmetricEncryption
5
- module Utils
6
- class AwsTest < Minitest::Test
7
- describe SymmetricEncryption::Utils::Aws do
8
- before do
9
- unless (ENV['AWS_ACCESS_KEY_ID'] && ENV['AWS_SECRET_ACCESS_KEY']) || ENV['AWS_CONFIG_FILE']
10
- # For example: export AWS_CONFIG_FILE=~/.aws/credentials
11
- skip 'Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY, or AWS_CONFIG_FILE to run AWS KMS tests'
12
- end
13
- end
14
-
15
- let :region do
16
- 'us-east-1'
17
- end
18
-
19
- let :master_key_alias do
20
- 'alias/symmetric-encryption/test'
21
- end
22
-
23
- let :aws do
24
- SymmetricEncryption::Utils::Aws.new(region: region, master_key_alias: master_key_alias)
25
- end
26
-
27
- describe '#key_spec' do
28
- it 'converts aes-256-cbc' do
29
- assert_equal 'AES_256', aws.key_spec('aes-256-cbc')
30
- end
31
-
32
- it 'converts aes-128-cbc' do
33
- assert_equal 'AES_128', aws.key_spec('aes-128-cbc')
34
- end
35
- end
36
-
37
- describe '#create_master_key' do
38
- it 'creates a new master key' do
39
- skip 'Only run if really needed, gets tested once as part of the CMK auto-create'
40
- aws.delete_master_key(retention_days: 7)
41
- aws.create_master_key
42
- end
43
- end
44
-
45
- describe '#generate_data_key' do
46
- it 'creates a new data key' do
47
- assert aws.generate_data_key('aes-128-cbc')
48
- end
49
- end
50
-
51
- describe '#generate_encrypted_data_key' do
52
- it 'creates a new data key' do
53
- assert aws.generate_encrypted_data_key('aes-128-cbc')
54
- end
55
- end
56
-
57
- describe '#encrypt' do
58
- it 'encrypts a block of data' do
59
- assert aws.encrypt('hello')
60
- end
61
- end
62
-
63
- describe '#decrypt' do
64
- it 'decrypts a previously encrypted block of data' do
65
- message = 'hello world this is a top secret message'
66
- encrypted = aws.encrypt(message)
67
- decrypted = aws.decrypt(encrypted)
68
- assert_equal message, decrypted
69
- end
70
- end
71
- end
72
- end
73
- end
74
- end