eco-helpers 2.4.8 → 2.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -1
  3. data/eco-helpers.gemspec +17 -17
  4. data/lib/eco/api/common/class_auto_loader.rb +8 -3
  5. data/lib/eco/api/common/loaders/base.rb +5 -1
  6. data/lib/eco/api/common/loaders/case_base.rb +2 -3
  7. data/lib/eco/api/common/people/default_parsers/csv_parser.rb +97 -47
  8. data/lib/eco/api/common/people/default_parsers/select_parser.rb +2 -2
  9. data/lib/eco/api/common/people/default_parsers/xls_parser.rb +0 -1
  10. data/lib/eco/api/common/people/entry_factory.rb +13 -8
  11. data/lib/eco/api/common/people/person_attribute_parser.rb +1 -1
  12. data/lib/eco/api/common/people/person_entry_attribute_mapper.rb +2 -2
  13. data/lib/eco/api/common/people/person_parser.rb +1 -1
  14. data/lib/eco/api/common/session/base_session.rb +1 -2
  15. data/lib/eco/api/common/session/environment.rb +6 -10
  16. data/lib/eco/api/common/session/helpers/prompt_user.rb +18 -18
  17. data/lib/eco/api/common/session/logger.rb +2 -2
  18. data/lib/eco/api/common/session/mailer.rb +1 -3
  19. data/lib/eco/api/common/session/s3_uploader.rb +1 -3
  20. data/lib/eco/api/common/session/sftp.rb +6 -4
  21. data/lib/eco/api/common/version_patches/ecoportal_api/external_person.rb +5 -4
  22. data/lib/eco/api/error.rb +5 -5
  23. data/lib/eco/api/session/config/api.rb +4 -2
  24. data/lib/eco/api/usecases/base_case.rb +0 -2
  25. data/lib/eco/api/usecases/base_io.rb +0 -3
  26. data/lib/eco/api/usecases/default_cases/samples/sftp_case.rb +1 -1
  27. data/lib/eco/api/usecases/ooze_samples/ooze_from_doc_case.rb +1 -2
  28. data/lib/eco/api/usecases/ooze_samples/ooze_run_base_case.rb +0 -1
  29. data/lib/eco/api/usecases/ooze_samples/ooze_update_case.rb +0 -1
  30. data/lib/eco/api/usecases/ooze_samples/register_export_case.rb +1 -1
  31. data/lib/eco/api/usecases/ooze_samples/register_update_case.rb +0 -2
  32. data/lib/eco/api/usecases/ooze_samples/target_oozes_update_case.rb +0 -1
  33. data/lib/eco/api/usecases/ooze_samples.rb +0 -1
  34. data/lib/eco/api/usecases/use_case.rb +30 -1
  35. data/lib/eco/api/usecases/use_case_chain.rb +1 -4
  36. data/lib/eco/api/usecases/use_case_io.rb +0 -2
  37. data/lib/eco/api/usecases.rb +4 -4
  38. data/lib/eco/api.rb +0 -2
  39. data/lib/eco/cli/config/default/options.rb +11 -1
  40. data/lib/eco/cli/scripting/arguments.rb +1 -1
  41. data/lib/eco/csv.rb +4 -7
  42. data/lib/eco/data/files/directory.rb +0 -3
  43. data/lib/eco/data/files/encoding.rb +75 -0
  44. data/lib/eco/data/files/helpers.rb +15 -37
  45. data/lib/eco/data/files.rb +1 -0
  46. data/lib/eco/data/fuzzy_match.rb +8 -4
  47. data/lib/eco/data.rb +0 -1
  48. data/lib/eco/version.rb +1 -1
  49. data/lib/eco-helpers.rb +1 -1
  50. metadata +23 -24
  51. data/lib/eco/data/crypto/encryption.rb +0 -321
  52. data/lib/eco/data/crypto.rb +0 -7
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eco-helpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.8
4
+ version: 2.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oscar Segura
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: 2.4.8
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '2.5'
22
+ version: '3'
23
23
  type: :development
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: 2.4.8
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '2.5'
32
+ version: '3'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: rspec
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -39,7 +39,7 @@ dependencies:
39
39
  version: 3.10.0
40
40
  - - "<"
41
41
  - !ruby/object:Gem::Version
42
- version: '3.11'
42
+ version: '4'
43
43
  type: :development
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
@@ -49,7 +49,7 @@ dependencies:
49
49
  version: 3.10.0
50
50
  - - "<"
51
51
  - !ruby/object:Gem::Version
52
- version: '3.11'
52
+ version: '4'
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: rake
55
55
  requirement: !ruby/object:Gem::Requirement
@@ -59,7 +59,7 @@ dependencies:
59
59
  version: 13.0.3
60
60
  - - "<"
61
61
  - !ruby/object:Gem::Version
62
- version: '13.1'
62
+ version: '14'
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
@@ -69,7 +69,7 @@ dependencies:
69
69
  version: 13.0.3
70
70
  - - "<"
71
71
  - !ruby/object:Gem::Version
72
- version: '13.1'
72
+ version: '14'
73
73
  - !ruby/object:Gem::Dependency
74
74
  name: yard
75
75
  requirement: !ruby/object:Gem::Requirement
@@ -79,7 +79,7 @@ dependencies:
79
79
  version: 0.9.26
80
80
  - - "<"
81
81
  - !ruby/object:Gem::Version
82
- version: '0.10'
82
+ version: '1'
83
83
  type: :development
84
84
  prerelease: false
85
85
  version_requirements: !ruby/object:Gem::Requirement
@@ -89,7 +89,7 @@ dependencies:
89
89
  version: 0.9.26
90
90
  - - "<"
91
91
  - !ruby/object:Gem::Version
92
- version: '0.10'
92
+ version: '1'
93
93
  - !ruby/object:Gem::Dependency
94
94
  name: redcarpet
95
95
  requirement: !ruby/object:Gem::Requirement
@@ -99,7 +99,7 @@ dependencies:
99
99
  version: 3.5.1
100
100
  - - "<"
101
101
  - !ruby/object:Gem::Version
102
- version: '3.6'
102
+ version: '4'
103
103
  type: :development
104
104
  prerelease: false
105
105
  version_requirements: !ruby/object:Gem::Requirement
@@ -109,14 +109,14 @@ dependencies:
109
109
  version: 3.5.1
110
110
  - - "<"
111
111
  - !ruby/object:Gem::Version
112
- version: '3.6'
112
+ version: '4'
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: ecoportal-api
115
115
  requirement: !ruby/object:Gem::Requirement
116
116
  requirements:
117
117
  - - ">="
118
118
  - !ruby/object:Gem::Version
119
- version: 0.9.3
119
+ version: 0.9.4
120
120
  - - "<"
121
121
  - !ruby/object:Gem::Version
122
122
  version: '0.10'
@@ -126,7 +126,7 @@ dependencies:
126
126
  requirements:
127
127
  - - ">="
128
128
  - !ruby/object:Gem::Version
129
- version: 0.9.3
129
+ version: 0.9.4
130
130
  - - "<"
131
131
  - !ruby/object:Gem::Version
132
132
  version: '0.10'
@@ -136,7 +136,7 @@ dependencies:
136
136
  requirements:
137
137
  - - ">="
138
138
  - !ruby/object:Gem::Version
139
- version: 1.1.1
139
+ version: 1.1.2
140
140
  - - "<"
141
141
  - !ruby/object:Gem::Version
142
142
  version: '1.2'
@@ -146,7 +146,7 @@ dependencies:
146
146
  requirements:
147
147
  - - ">="
148
148
  - !ruby/object:Gem::Version
149
- version: 1.1.1
149
+ version: 1.1.2
150
150
  - - "<"
151
151
  - !ruby/object:Gem::Version
152
152
  version: '1.2'
@@ -156,7 +156,7 @@ dependencies:
156
156
  requirements:
157
157
  - - ">="
158
158
  - !ruby/object:Gem::Version
159
- version: 0.3.5
159
+ version: 0.3.7
160
160
  - - "<"
161
161
  - !ruby/object:Gem::Version
162
162
  version: '0.4'
@@ -166,7 +166,7 @@ dependencies:
166
166
  requirements:
167
167
  - - ">="
168
168
  - !ruby/object:Gem::Version
169
- version: 0.3.5
169
+ version: 0.3.7
170
170
  - - "<"
171
171
  - !ruby/object:Gem::Version
172
172
  version: '0.4'
@@ -219,7 +219,7 @@ dependencies:
219
219
  version: 2.7.6
220
220
  - - "<"
221
221
  - !ruby/object:Gem::Version
222
- version: '2.8'
222
+ version: '3'
223
223
  type: :runtime
224
224
  prerelease: false
225
225
  version_requirements: !ruby/object:Gem::Requirement
@@ -229,7 +229,7 @@ dependencies:
229
229
  version: 2.7.6
230
230
  - - "<"
231
231
  - !ruby/object:Gem::Version
232
- version: '2.8'
232
+ version: '3'
233
233
  - !ruby/object:Gem::Dependency
234
234
  name: net-sftp
235
235
  requirement: !ruby/object:Gem::Requirement
@@ -239,7 +239,7 @@ dependencies:
239
239
  version: 3.0.0
240
240
  - - "<"
241
241
  - !ruby/object:Gem::Version
242
- version: '3.1'
242
+ version: '4'
243
243
  type: :runtime
244
244
  prerelease: false
245
245
  version_requirements: !ruby/object:Gem::Requirement
@@ -249,7 +249,7 @@ dependencies:
249
249
  version: 3.0.0
250
250
  - - "<"
251
251
  - !ruby/object:Gem::Version
252
- version: '3.1'
252
+ version: '4'
253
253
  - !ruby/object:Gem::Dependency
254
254
  name: hashdiff
255
255
  requirement: !ruby/object:Gem::Requirement
@@ -644,10 +644,9 @@ files:
644
644
  - lib/eco/csv.rb
645
645
  - lib/eco/csv/table.rb
646
646
  - lib/eco/data.rb
647
- - lib/eco/data/crypto.rb
648
- - lib/eco/data/crypto/encryption.rb
649
647
  - lib/eco/data/files.rb
650
648
  - lib/eco/data/files/directory.rb
649
+ - lib/eco/data/files/encoding.rb
651
650
  - lib/eco/data/files/file_pattern.rb
652
651
  - lib/eco/data/files/helpers.rb
653
652
  - lib/eco/data/fuzzy_match.rb
@@ -698,7 +697,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
698
697
  - !ruby/object:Gem::Version
699
698
  version: '0'
700
699
  requirements: []
701
- rubygems_version: 3.1.4
700
+ rubygems_version: 3.4.12
702
701
  signing_key:
703
702
  specification_version: 4
704
703
  summary: eco-helpers to manage people api cases
@@ -1,321 +0,0 @@
1
- require 'openssl'
2
- # 'json'
3
- require 'base64'
4
- #require 'pp'
5
-
6
- require_relative '../../cli/scripting'
7
-
8
- # see some ramblings here: http://distributed-frostbite.blogspot.com/2010/06/file-encryption-in-ruby-with-openssl.html
9
-
10
-
11
- def run! # this will run only if called from command line (not when require'd nor load'd)
12
- include Eco::CLI::Scripting
13
- include Eco::Data::Crypto
14
- # script arguments
15
- keygen = get_arg("-keygen")
16
- filename = get_arg("-keygen", with_param: true)
17
- ssh = get_arg("-ssh")
18
- length = get_arg("-length", with_param: true)
19
- check_rsa_pairs = get_arg("-keypairs")
20
- key_filename = get_arg("-keypairs", with_param: true)
21
-
22
- # methods
23
- case true
24
- when keygen
25
- puts "++ keygen RSA ++"
26
- #pp ::OpenSSL.constants.sort
27
- cr = Eco::Data::Crypto::OpenSSL.new
28
- case true
29
- when ssh
30
- puts "think about installing this library: https://rubygems.org/gems/sshkey"
31
- puts "GitHub: https://github.com/bensie/sshkey"
32
- puts "or add this Ruby solution to convert to ssh-rsa: https://stackoverflow.com/a/3162593/4352306"
33
- exit(1)
34
- cr.rsa_keygen_ssh(filename: filename)
35
- else
36
- cr.rsa_keygen(filename: filename)
37
- end
38
- when check_rsa_pairs
39
- puts "++ checking file pairs ++"
40
- begin
41
- key_filename = "rsa" if !key_filename
42
- priv = File.read(key_filename + '.pem')
43
- pub = File.read(key_filename + '.pub')
44
- rescue
45
- puts "could not find files with basename: #{key_filename}"
46
- exit(1)
47
- end
48
- cr = Eco::Data::Crypto::OpenSSL.new
49
- equals = cr.rsa_keypairs?(priv, pub)
50
- if equals
51
- puts "the pair #{key_filename} seem to be for one to another!"
52
- else
53
- puts "those files with base name #{key_filename} are not a rsa pair"
54
- end
55
- end
56
- end
57
-
58
-
59
- module Eco
60
- module Data
61
- #TODO study how to encrypt uniquely the api key in the configuration file
62
- #TODO study how RSA could boost team-shared Drive folder (updates, and people files should be encrypted via public key)
63
- module Crypto
64
- # file conf definitions
65
- THIS_FILENAME = __FILE__
66
- MY_NAME = File.basename(THIS_FILENAME, File.extname(THIS_FILENAME)) # ".rb"
67
- PATH = File.dirname(THIS_FILENAME)
68
- WORKING_DIR = PATH + "/" + MY_NAME
69
- PARSER_FILE = WORKING_DIR + "/json_parser.json" # .dll
70
-
71
- class OpenSSL
72
- DEFAULT_KEY_LENGTH = 256
73
- DEFAULT_RSA_LENGTH = 2048
74
- SALT_LENGTH = 128
75
- SALT_SEED = "$%!@_halt9000"
76
- BLOCK_OCTETS = 512
77
- attr_accessor :salt_seed
78
- attr_reader :digest, :pkcs5, :kdf, :cipher, :rsa
79
- attr_reader :salt
80
- def initialize(init = {})
81
- @digest = ::OpenSSL::Digest
82
- @pkcs5 = ::OpenSSL::PKCS5
83
- #@kdf = ::OpenSSL::KDF
84
- @cipher = ::OpenSSL::Cipher
85
- self.salt_seed = SALT_SEED
86
- @rsa = ::OpenSSL::PKey::RSA
87
- end
88
- def salt_seed=(value)
89
- @salt_seed = value
90
- @salt = self.pbkdf2(@salt_seed, salt: @salt_seed, length: SALT_LENGTH)
91
- end
92
- def sha256 (str = nil)
93
- sha = @digest.SHA256.new
94
- digest = sha.digest(str) unless !str
95
- sha.reset
96
- digest
97
- end
98
- def sha512 (str = nil)
99
- sha = @digest.SHA512.new
100
- digest = sha.digest(str) unless !str
101
- sha.reset
102
- digest
103
- end
104
- # default hmac hash to "sha256" -> https://github.com/hueniverse/iron/issues/55
105
- def pbkdf2 (pass, salt: @salt || "salt", iterations: 1000, length: DEFAULT_KEY_LENGTH, hash: "sha256")
106
- octets = length.div(8)
107
- #puts "this has been called"
108
- #puts "pass: #{pass}"
109
- #puts "salt: #{salt}"
110
- #puts "iterations: #{iterations}"
111
- #puts "length: #{length}"
112
- #puts "hash: #{hash}"
113
- @pkcs5.pbkdf2_hmac(pass, salt, iterations, octets, hash)
114
- end
115
- def pbkdf2_sha1 (pass, salt: @salt, iterations: 1000, length: DEFAULT_KEY_LENGTH)
116
- #self.pbkdf2(pass, salt: salt, iterations: iternations, length: length, hash: "sha1")
117
- @pkcs5.pbkdf2_hmac(pass, salt, iterations, octets, "sha1")
118
- end
119
- =begin
120
- def scrypt (pass, salt: @salt, cost: 14, length: DEFAULT_KEY_LENGTH)
121
- block_size = 8
122
- parallelization = 1
123
- octets = length.div(8)
124
- @kdf.scrypt(pass, salt: salt, N: 2**cost, r: block_size, p: parallelization, length: octets)
125
- end
126
- =end
127
- def aes256_pass(pass)
128
- self.pbkdf2(pass, length: 256)
129
- end
130
- def aes256_encrypt(data, key: nil, iv: nil, block_octets: BLOCK_OCTETS)
131
- block_bits = block_bits * 8
132
- cipher = @cipher.new('aes-256-cbc')
133
- cipher.encrypt
134
-
135
- if key ; cipher.key = key
136
- else ; key = cipher.random_key
137
- end
138
- if iv ; cipher.iv = iv
139
- else ; iv = cipher.random_iv
140
- end
141
-
142
- str_c = ""
143
- while str.length > 0
144
- str_c += cipher.update(str.slice!(0, block_bits))
145
- end
146
- str_c += cipher.final
147
- return str_c
148
- #EncryptedData.new({content: str_c, key: key, iv: iv})
149
-
150
-
151
- end
152
- def aes256_decrypt(data, key: , iv: , block_octets: BLOCK_OCTETS)
153
- block_bits = block_bits * 8
154
- #validation = encrypted_data && encrypted_data.key && encrypted_data.iv
155
- # return nil unless validation
156
- cipher = @cipher.new('aes-256-cbc')
157
- cipher.decrypt
158
- cipher.key = key
159
- cipher.iv = iv
160
- #cipher.key = encrypted_data.key
161
- #cipher.iv = encrypted_data.iv
162
- #str_c = encrypted_data.content
163
- str_c = data
164
- str = ""
165
- while str_c.length > 0
166
- str += cipher.update(str_c.slice!(0, block_bits))
167
- #puts str[-50..-1] || str
168
- end
169
- str += cipher.final
170
- return str
171
- end
172
- def rsa_keygen(length = DEFAULT_RSA_LENGTH, filename: "rsa")
173
- filename = "rsa" if !filename
174
- key = @rsa.new(length)
175
- File.open('./' + filename + '.pem',"w") {|fd| fd << key.to_pem }
176
- File.open('./' + filename + '.pub',"w") {|fd| fd << key.public_key.to_pem }
177
- end
178
- def rsa_keygen_ssh(length = DEFAULT_RSA_LENGTH, filename: "rsa")
179
- # to do conersion pem to ssh-rsa: https://stackoverflow.com/a/3162593/4352306
180
- # conversion explained here: http://blog.oddbit.com/2011/05/08/converting-openssh-public-keys/
181
- # much simpler developed in php here: https://stackoverflow.com/a/5524323/4352306
182
- filename = "rsa" if !filename
183
- key = @rsa.new(length)
184
- File.open('./' + filename + '.der',"w") {|fd| fd << key.ssh_type }
185
- File.open('./' + filename + '.pub',"w") {|fd| fd << key.public_key.ssh_type }
186
- end
187
- def rsa_keypairs?(private_key, public_key)
188
- str_original = "See, my mule don’t like people laughing"
189
-
190
- pub_key = @rsa.new(public_key)
191
- str_original.force_encoding(Encoding::UTF_8)
192
- encrypted_data = Base64.encode64(pub_key.public_encrypt(str_original))
193
-
194
- priv_key = @rsa.new(private_key)
195
- begin # see here: https://stackoverflow.com/a/13251160/4352306 (padding error when false pub key)
196
- decrypted_data = priv_key.private_decrypt(Base64.decode64(encrypted_data))
197
- # OpenSSL core Ruby library is written in C which uses different encoding (ASCII-8BIT)
198
- # that's why we force UTF-8 encoding (before and after encryption)
199
- # see this answer: https://stackoverflow.com/a/27326915/4352306
200
- decrypted_data.force_encoding(Encoding::UTF_8)
201
- rescue
202
- return false
203
- end
204
-
205
- puts "encrypted string: #{str_original}"
206
- puts "decrypted string: #{decrypted_data}"
207
- return (decrypted_data == str_original)
208
- end
209
- end
210
-
211
-
212
- class EncryptedData
213
- attr_reader :key, :iv, :content
214
- def initialize(init = {})
215
- @key = init[:key]
216
- @iv = init[:iv]
217
- @content = init[:content]
218
- @sha = sha256(@content)
219
- load() if !@key || !@iv
220
- end
221
- def load (file = nil)
222
- parser = get_parser(file)
223
- sha64 = Base64.encode64(@sha) if @sha
224
- if parser.key?(sha64)
225
- #puts "found key!"
226
- meta = parser[sha64]
227
- key64, iv64 = meta.values_at("key", "iv")
228
- @key = Base64.decode64(key64) if key64
229
- @iv = Base64.decode64(iv64) if iv64
230
- else
231
- #puts "key not found! #{sha64}"
232
- end
233
- end
234
- def save (file = nil)
235
- parser = get_parser(file)
236
- sha64 = Base64.encode64(@sha) if @sha
237
- #puts "save key: #{sha64}"
238
- if parser.key?(sha64)
239
- meta = parser[sha64]
240
- else
241
- meta = {key: nil, iv: nil}
242
- parser[sha64] = meta
243
- end
244
- meta[:key] = Base64.encode64(@key) if @key
245
- meta[:iv] = Base64.encode64(@iv) if @iv
246
- set_parser(file, parser)
247
- end
248
-
249
- private
250
- def get_parser (file = nil)
251
- file = PARSER_FILE if !file
252
- # create the directory unless it exists
253
- Dir.mkdir(WORKING_DIR) unless Dir.exist?(WORKING_DIR)
254
- parser = {}
255
- if File.file?(file)
256
- fd = File.open(file,"r")
257
- parser = JSON.load(fd)
258
- fd.close
259
- end
260
- return parser
261
- end
262
- def set_parser (file = nil, parser = {})
263
- file = PARSER_FILE if !file
264
- # create the directory unless it exists
265
- Dir.mkdir(WORKING_DIR) unless Dir.exist?(WORKING_DIR)
266
- fd = File.open(file,"w")
267
- fd << parser.to_json
268
- fd.close
269
- end
270
- def sha256 (str = nil)
271
- sha = OpenSSL::Digest::SHA256.new
272
- digest = sha.digest(str) unless !str
273
- sha.reset
274
- digest
275
- end
276
- end
277
-
278
- def self.encrypt (str)
279
- cipher = OpenSSL::Cipher.new('aes-256-cbc')
280
- cipher.encrypt
281
- key = cipher.random_key
282
- iv = cipher.random_iv
283
-
284
- str_c = ""
285
- while str.length > 0
286
- str_c += cipher.update(str.slice!(0, 4096))
287
- end
288
- str_c += cipher.final
289
- EncryptedData.new({content: str_c, key: key, iv: iv})
290
- end
291
-
292
- def self.decrypt (encrypted_data)
293
- unless encrypted_data && encrypted_data.key && encrypted_data.iv
294
- return nil
295
- end
296
- cipher = OpenSSL::Cipher.new('aes-256-cbc')
297
- cipher.decrypt
298
- cipher.key = encrypted_data.key
299
- cipher.iv = encrypted_data.iv
300
- str_c = encrypted_data.content
301
- str = ""
302
- while str_c.length > 0
303
- str += cipher.update(str_c.slice!(0, 4096))
304
- #puts str[-50..-1] || str
305
- end
306
- str += cipher.final
307
- return str
308
- end
309
-
310
- end
311
- =begin
312
- class Includer
313
- include Crypto
314
- end
315
- CRYPTO = Includer.new
316
- =end
317
- end
318
- end
319
-
320
-
321
- run! if __FILE__==$0
@@ -1,7 +0,0 @@
1
- module Eco
2
- module Data
3
- module Crypto
4
- end
5
- end
6
- end
7
- require_relative 'crypto/encryption'