aws-sdk-resources 2.11.561 → 2.11.566
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/lib/aws-sdk-resources/services/s3.rb +1 -0
- data/lib/aws-sdk-resources/services/s3/encryption.rb +3 -0
- data/lib/aws-sdk-resources/services/s3/encryption/client.rb +24 -7
- data/lib/aws-sdk-resources/services/s3/encryption/decrypt_handler.rb +77 -26
- data/lib/aws-sdk-resources/services/s3/encryption/default_cipher_provider.rb +43 -5
- data/lib/aws-sdk-resources/services/s3/encryption/default_key_provider.rb +2 -0
- data/lib/aws-sdk-resources/services/s3/encryption/encrypt_handler.rb +13 -2
- data/lib/aws-sdk-resources/services/s3/encryption/errors.rb +2 -0
- data/lib/aws-sdk-resources/services/s3/encryption/io_auth_decrypter.rb +2 -0
- data/lib/aws-sdk-resources/services/s3/encryption/io_decrypter.rb +11 -3
- data/lib/aws-sdk-resources/services/s3/encryption/io_encrypter.rb +2 -0
- data/lib/aws-sdk-resources/services/s3/encryption/key_provider.rb +2 -0
- data/lib/aws-sdk-resources/services/s3/encryption/kms_cipher_provider.rb +36 -3
- data/lib/aws-sdk-resources/services/s3/encryption/materials.rb +8 -6
- data/lib/aws-sdk-resources/services/s3/encryption/utils.rb +25 -0
- data/lib/aws-sdk-resources/services/s3/encryptionV2/client.rb +561 -0
- data/lib/aws-sdk-resources/services/s3/encryptionV2/decrypt_handler.rb +214 -0
- data/lib/aws-sdk-resources/services/s3/encryptionV2/default_cipher_provider.rb +170 -0
- data/lib/aws-sdk-resources/services/s3/encryptionV2/default_key_provider.rb +40 -0
- data/lib/aws-sdk-resources/services/s3/encryptionV2/encrypt_handler.rb +69 -0
- data/lib/aws-sdk-resources/services/s3/encryptionV2/errors.rb +37 -0
- data/lib/aws-sdk-resources/services/s3/encryptionV2/io_auth_decrypter.rb +58 -0
- data/lib/aws-sdk-resources/services/s3/encryptionV2/io_decrypter.rb +37 -0
- data/lib/aws-sdk-resources/services/s3/encryptionV2/io_encrypter.rb +73 -0
- data/lib/aws-sdk-resources/services/s3/encryptionV2/key_provider.rb +31 -0
- data/lib/aws-sdk-resources/services/s3/encryptionV2/kms_cipher_provider.rb +169 -0
- data/lib/aws-sdk-resources/services/s3/encryptionV2/materials.rb +60 -0
- data/lib/aws-sdk-resources/services/s3/encryptionV2/utils.rb +103 -0
- data/lib/aws-sdk-resources/services/s3/encryption_v2.rb +24 -0
- metadata +18 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a053b10dceb940a82b9af9b44a0c545d8dc177ed74b4c0f60aa046899a3e5167
|
4
|
+
data.tar.gz: 7d801de7114f99cb717865d593f9ee074ae783602e4847d0296c8346811ce539
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bcfde9c4b3155f005d3708eb780bc9bf3ee6cab676c48f76a45da64fca8c470fdfdf5aef7313188fcabfcc532efd20b57e9edb27de0956d40b7481f79e7364ff
|
7
|
+
data.tar.gz: 5f5209c5385cf8f671f8ec6c2e13f9b1477111dd6297925527b50c975338cf7322fe8610d4e7d04309ea791b9f7008fe2bbd191c065fd47720c400fd962e3ebf
|
@@ -7,6 +7,7 @@ module Aws
|
|
7
7
|
require 'aws-sdk-resources/services/s3/multipart_upload'
|
8
8
|
|
9
9
|
autoload :Encryption, 'aws-sdk-resources/services/s3/encryption'
|
10
|
+
autoload :EncryptionV2, 'aws-sdk-resources/services/s3/encryption_v2'
|
10
11
|
autoload :FilePart, 'aws-sdk-resources/services/s3/file_part'
|
11
12
|
autoload :FileUploader, 'aws-sdk-resources/services/s3/file_uploader'
|
12
13
|
autoload :FileDownloader, 'aws-sdk-resources/services/s3/file_downloader'
|
@@ -2,6 +2,9 @@ module Aws
|
|
2
2
|
module S3
|
3
3
|
module Encryption
|
4
4
|
|
5
|
+
AES_GCM_TAG_LEN_BYTES = 16
|
6
|
+
EC_USER_AGENT = 'S3CryptoV1n'
|
7
|
+
|
5
8
|
autoload :Client, 'aws-sdk-resources/services/s3/encryption/client'
|
6
9
|
autoload :DecryptHandler, 'aws-sdk-resources/services/s3/encryption/decrypt_handler'
|
7
10
|
autoload :DefaultCipherProvider, 'aws-sdk-resources/services/s3/encryption/default_cipher_provider'
|
@@ -1,6 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
|
1
5
|
module Aws
|
2
6
|
module S3
|
3
7
|
|
8
|
+
# [MAINTENANCE MODE] There is a new version of the Encryption Client.
|
9
|
+
# AWS strongly recommends upgrading to the {Aws::S3::EncryptionV2::Client},
|
10
|
+
# which provides updated data security best practices.
|
11
|
+
# See documentation for {Aws::S3::EncryptionV2::Client}.
|
4
12
|
# Provides an encryption client that encrypts and decrypts data client-side,
|
5
13
|
# storing the encrypted data in Amazon S3.
|
6
14
|
#
|
@@ -26,7 +34,7 @@ module Aws
|
|
26
34
|
# data client-side.
|
27
35
|
#
|
28
36
|
# One of the benefits of envelope encryption is that if your master key
|
29
|
-
# is compromised, you have the option of
|
37
|
+
# is compromised, you have the option of just re-encrypting the stored
|
30
38
|
# envelope symmetric keys, instead of re-encrypting all of the
|
31
39
|
# data in your account.
|
32
40
|
#
|
@@ -178,15 +186,17 @@ module Aws
|
|
178
186
|
class Client
|
179
187
|
|
180
188
|
extend Deprecations
|
189
|
+
extend Forwardable
|
190
|
+
def_delegators :@client, :config, :delete_object, :head_object, :build_request
|
181
191
|
|
182
|
-
# Creates a new encryption client. You must provide
|
192
|
+
# Creates a new encryption client. You must provide one of the following
|
183
193
|
# options:
|
184
194
|
#
|
185
195
|
# * `:encryption_key`
|
186
196
|
# * `:kms_key_id`
|
187
197
|
# * `:key_provider`
|
188
198
|
#
|
189
|
-
# You may also pass any other options accepted by
|
199
|
+
# You may also pass any other options accepted by `Client#initialize`.
|
190
200
|
#
|
191
201
|
# @option options [S3::Client] :client A basic S3 client that is used
|
192
202
|
# to make api calls. If a `:client` is not provided, a new {S3::Client}
|
@@ -223,6 +233,13 @@ module Aws
|
|
223
233
|
@envelope_location = extract_location(options)
|
224
234
|
@instruction_file_suffix = extract_suffix(options)
|
225
235
|
end
|
236
|
+
deprecated :initialize,
|
237
|
+
message:
|
238
|
+
'[MAINTENANCE MODE] This version of the S3 Encryption client is currently in maintenance mode. ' \
|
239
|
+
'AWS strongly recommends upgrading to the Aws::S3::EncryptionV2::Client, ' \
|
240
|
+
'which provides updated data security best practices. ' \
|
241
|
+
'See documentation for Aws::S3::EncryptionV2::Client.'
|
242
|
+
|
226
243
|
|
227
244
|
# @return [S3::Client]
|
228
245
|
attr_reader :client
|
@@ -327,7 +344,7 @@ module Aws
|
|
327
344
|
elsif options[:encryption_key]
|
328
345
|
DefaultKeyProvider.new(options)
|
329
346
|
else
|
330
|
-
msg =
|
347
|
+
msg = 'you must pass a :kms_key_id, :key_provider, or :encryption_key'
|
331
348
|
raise ArgumentError, msg
|
332
349
|
end
|
333
350
|
end
|
@@ -347,8 +364,8 @@ module Aws
|
|
347
364
|
if [:metadata, :instruction_file].include?(location)
|
348
365
|
location
|
349
366
|
else
|
350
|
-
msg =
|
351
|
-
|
367
|
+
msg = ':envelope_location must be :metadata or :instruction_file '\
|
368
|
+
"got #{location.inspect}"
|
352
369
|
raise ArgumentError, msg
|
353
370
|
end
|
354
371
|
end
|
@@ -358,7 +375,7 @@ module Aws
|
|
358
375
|
if String === suffix
|
359
376
|
suffix
|
360
377
|
else
|
361
|
-
msg =
|
378
|
+
msg = ':instruction_file_suffix must be a String'
|
362
379
|
raise ArgumentError, msg
|
363
380
|
end
|
364
381
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'base64'
|
2
4
|
|
3
5
|
module Aws
|
@@ -5,6 +7,7 @@ module Aws
|
|
5
7
|
module Encryption
|
6
8
|
# @api private
|
7
9
|
class DecryptHandler < Seahorse::Client::Handler
|
10
|
+
@@warned_response_target_proc = false
|
8
11
|
|
9
12
|
V1_ENVELOPE_KEYS = %w(
|
10
13
|
x-amz-key
|
@@ -20,15 +23,39 @@ module Aws
|
|
20
23
|
x-amz-matdesc
|
21
24
|
)
|
22
25
|
|
23
|
-
|
26
|
+
V2_OPTIONAL_KEYS = %w(x-amz-tag-len)
|
27
|
+
|
28
|
+
POSSIBLE_ENVELOPE_KEYS = (V1_ENVELOPE_KEYS +
|
29
|
+
V2_ENVELOPE_KEYS + V2_OPTIONAL_KEYS).uniq
|
30
|
+
|
31
|
+
POSSIBLE_WRAPPING_FORMATS = %w(
|
32
|
+
AES/GCM
|
33
|
+
kms
|
34
|
+
kms+context
|
35
|
+
RSA-OAEP-SHA1
|
36
|
+
)
|
24
37
|
|
25
38
|
POSSIBLE_ENCRYPTION_FORMATS = %w(
|
26
39
|
AES/GCM/NoPadding
|
27
40
|
AES/CBC/PKCS5Padding
|
41
|
+
AES/CBC/PKCS7Padding
|
28
42
|
)
|
29
43
|
|
44
|
+
AUTH_REQUIRED_CEK_ALGS = %w(AES/GCM/NoPadding)
|
45
|
+
|
30
46
|
def call(context)
|
31
47
|
attach_http_event_listeners(context)
|
48
|
+
apply_cse_user_agent(context)
|
49
|
+
|
50
|
+
if context[:response_target].is_a?(Proc) && !@@warned_response_target_proc
|
51
|
+
@@warned_response_target_proc = true
|
52
|
+
warn(':response_target is a Proc, or a block was provided. ' \
|
53
|
+
'Read the entire object to the ' \
|
54
|
+
'end before you start using the decrypted data. This is to ' \
|
55
|
+
'verify that the object has not been modified since it ' \
|
56
|
+
'was encrypted.')
|
57
|
+
end
|
58
|
+
|
32
59
|
@handler.call(context)
|
33
60
|
end
|
34
61
|
|
@@ -37,9 +64,9 @@ module Aws
|
|
37
64
|
def attach_http_event_listeners(context)
|
38
65
|
|
39
66
|
context.http_response.on_headers(200) do
|
40
|
-
cipher = decryption_cipher(context)
|
41
|
-
decrypter = body_contains_auth_tag?(
|
42
|
-
authenticated_decrypter(context, cipher) :
|
67
|
+
cipher, envelope = decryption_cipher(context)
|
68
|
+
decrypter = body_contains_auth_tag?(envelope) ?
|
69
|
+
authenticated_decrypter(context, cipher, envelope) :
|
43
70
|
IODecrypter.new(cipher, context.http_response.body)
|
44
71
|
context.http_response.body = decrypter
|
45
72
|
end
|
@@ -59,8 +86,13 @@ module Aws
|
|
59
86
|
end
|
60
87
|
|
61
88
|
def decryption_cipher(context)
|
62
|
-
if envelope = get_encryption_envelope(context)
|
63
|
-
context[:encryption][:cipher_provider]
|
89
|
+
if (envelope = get_encryption_envelope(context))
|
90
|
+
cipher = context[:encryption][:cipher_provider]
|
91
|
+
.decryption_cipher(
|
92
|
+
envelope,
|
93
|
+
context[:encryption]
|
94
|
+
)
|
95
|
+
[cipher, envelope]
|
64
96
|
else
|
65
97
|
raise Errors::DecryptionError, "unable to locate encryption envelope"
|
66
98
|
end
|
@@ -96,13 +128,12 @@ module Aws
|
|
96
128
|
end
|
97
129
|
|
98
130
|
def extract_envelope(hash)
|
131
|
+
return nil unless hash
|
99
132
|
return v1_envelope(hash) if hash.key?('x-amz-key')
|
100
133
|
return v2_envelope(hash) if hash.key?('x-amz-key-v2')
|
101
134
|
if hash.keys.any? { |key| key.match(/^x-amz-key-(.+)$/) }
|
102
135
|
msg = "unsupported envelope encryption version #{$1}"
|
103
136
|
raise Errors::DecryptionError, msg
|
104
|
-
else
|
105
|
-
nil # no envelope found
|
106
137
|
end
|
107
138
|
end
|
108
139
|
|
@@ -116,35 +147,31 @@ module Aws
|
|
116
147
|
msg = "unsupported content encrypting key (cek) format: #{alg}"
|
117
148
|
raise Errors::DecryptionError, msg
|
118
149
|
end
|
119
|
-
unless envelope['x-amz-wrap-alg']
|
120
|
-
# possible to support
|
121
|
-
# RSA/ECB/OAEPWithSHA-256AndMGF1Padding
|
150
|
+
unless POSSIBLE_WRAPPING_FORMATS.include? envelope['x-amz-wrap-alg']
|
122
151
|
alg = envelope['x-amz-wrap-alg'].inspect
|
123
152
|
msg = "unsupported key wrapping algorithm: #{alg}"
|
124
153
|
raise Errors::DecryptionError, msg
|
125
154
|
end
|
126
|
-
unless V2_ENVELOPE_KEYS
|
155
|
+
unless (missing_keys = V2_ENVELOPE_KEYS - envelope.keys).empty?
|
127
156
|
msg = "incomplete v2 encryption envelope:\n"
|
128
|
-
msg += "
|
129
|
-
msg += " got: #{envelope_keys.join(', ')}"
|
157
|
+
msg += " missing: #{missing_keys.join(',')}\n"
|
130
158
|
raise Errors::DecryptionError, msg
|
131
159
|
end
|
132
160
|
envelope
|
133
161
|
end
|
134
162
|
|
135
|
-
# When the x-amz-meta-x-amz-tag-len header is present, it indicates
|
136
|
-
# that the body of this object has a trailing auth tag. The header
|
137
|
-
# indicates the length of that tag.
|
138
|
-
#
|
139
163
|
# This method fetches the tag from the end of the object by
|
140
164
|
# making a GET Object w/range request. This auth tag is used
|
141
165
|
# to initialize the cipher, and the decrypter truncates the
|
142
166
|
# auth tag from the body when writing the final bytes.
|
143
|
-
def authenticated_decrypter(context, cipher)
|
167
|
+
def authenticated_decrypter(context, cipher, envelope)
|
168
|
+
if RUBY_VERSION.match(/1.9/)
|
169
|
+
raise "authenticated decryption not supported by OpenSSL in Ruby version ~> 1.9"
|
170
|
+
raise Aws::Errors::NonSupportedRubyVersionError, msg
|
171
|
+
end
|
144
172
|
http_resp = context.http_response
|
145
173
|
content_length = http_resp.headers['content-length'].to_i
|
146
|
-
auth_tag_length =
|
147
|
-
auth_tag_length = auth_tag_length.to_i / 8
|
174
|
+
auth_tag_length = auth_tag_length(envelope)
|
148
175
|
|
149
176
|
auth_tag = context.client.get_object(
|
150
177
|
bucket: context.params[:bucket],
|
@@ -156,16 +183,40 @@ module Aws
|
|
156
183
|
cipher.auth_data = ''
|
157
184
|
|
158
185
|
# The encrypted object contains both the cipher text
|
159
|
-
# plus a trailing auth tag.
|
160
|
-
|
161
|
-
decrypter = IOAuthDecrypter.new(
|
186
|
+
# plus a trailing auth tag.
|
187
|
+
IOAuthDecrypter.new(
|
162
188
|
io: http_resp.body,
|
163
189
|
encrypted_content_length: content_length - auth_tag_length,
|
164
190
|
cipher: cipher)
|
165
191
|
end
|
166
192
|
|
167
|
-
def body_contains_auth_tag?(
|
168
|
-
|
193
|
+
def body_contains_auth_tag?(envelope)
|
194
|
+
AUTH_REQUIRED_CEK_ALGS.include?(envelope['x-amz-cek-alg'])
|
195
|
+
end
|
196
|
+
|
197
|
+
# Determine the auth tag length from the algorithm
|
198
|
+
# Validate it against the value provided in the x-amz-tag-len
|
199
|
+
# Return the tag length in bytes
|
200
|
+
def auth_tag_length(envelope)
|
201
|
+
tag_length =
|
202
|
+
case envelope['x-amz-cek-alg']
|
203
|
+
when 'AES/GCM/NoPadding' then AES_GCM_TAG_LEN_BYTES
|
204
|
+
else
|
205
|
+
raise ArgumentError, 'Unsupported cek-alg: ' \
|
206
|
+
"#{envelope['x-amz-cek-alg']}"
|
207
|
+
end
|
208
|
+
if (tag_length * 8) != envelope['x-amz-tag-len'].to_i
|
209
|
+
raise Errors::DecryptionError, 'x-amz-tag-len does not match expected'
|
210
|
+
end
|
211
|
+
tag_length
|
212
|
+
end
|
213
|
+
|
214
|
+
def apply_cse_user_agent(context)
|
215
|
+
if context.config.user_agent_suffix.nil?
|
216
|
+
context.config.user_agent_suffix = EC_USER_AGENT
|
217
|
+
elsif !context.config.user_agent_suffix.include? EC_USER_AGENT
|
218
|
+
context.config.user_agent_suffix += " #{EC_USER_AGENT}"
|
219
|
+
end
|
169
220
|
end
|
170
221
|
|
171
222
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'base64'
|
2
4
|
|
3
5
|
module Aws
|
@@ -24,11 +26,48 @@ module Aws
|
|
24
26
|
|
25
27
|
# @return [Cipher] Given an encryption envelope, returns a
|
26
28
|
# decryption cipher.
|
27
|
-
def decryption_cipher(envelope)
|
29
|
+
def decryption_cipher(envelope, options = {})
|
28
30
|
master_key = @key_provider.key_for(envelope['x-amz-matdesc'])
|
29
|
-
|
30
|
-
|
31
|
-
|
31
|
+
if envelope.key? 'x-amz-key'
|
32
|
+
# Support for decryption of legacy objects
|
33
|
+
key = Utils.decrypt(master_key, decode64(envelope['x-amz-key']))
|
34
|
+
iv = decode64(envelope['x-amz-iv'])
|
35
|
+
Utils.aes_decryption_cipher(:CBC, key, iv)
|
36
|
+
else
|
37
|
+
if envelope['x-amz-cek-alg'] != 'AES/GCM/NoPadding'
|
38
|
+
raise ArgumentError, 'Unsupported cek-alg: ' \
|
39
|
+
"#{envelope['x-amz-cek-alg']}"
|
40
|
+
end
|
41
|
+
key =
|
42
|
+
case envelope['x-amz-wrap-alg']
|
43
|
+
when 'AES/GCM'
|
44
|
+
if master_key.is_a? OpenSSL::PKey::RSA
|
45
|
+
raise ArgumentError, 'Key mismatch - Client is configured' \
|
46
|
+
' with an RSA key and the x-amz-wrap-alg is AES/GCM.'
|
47
|
+
end
|
48
|
+
Utils.decrypt_aes_gcm(master_key,
|
49
|
+
decode64(envelope['x-amz-key-v2']),
|
50
|
+
envelope['x-amz-cek-alg'])
|
51
|
+
when 'RSA-OAEP-SHA1'
|
52
|
+
unless master_key.is_a? OpenSSL::PKey::RSA
|
53
|
+
raise ArgumentError, 'Key mismatch - Client is configured' \
|
54
|
+
' with an AES key and the x-amz-wrap-alg is RSA-OAEP-SHA1.'
|
55
|
+
end
|
56
|
+
key, cek_alg = Utils.decrypt_rsa(master_key, decode64(envelope['x-amz-key-v2']))
|
57
|
+
raise Errors::DecryptionError unless cek_alg == envelope['x-amz-cek-alg']
|
58
|
+
key
|
59
|
+
when 'kms+context'
|
60
|
+
raise ArgumentError, 'Key mismatch - Client is configured' \
|
61
|
+
' with a user provided key and the x-amz-wrap-alg is' \
|
62
|
+
' kms+context. Please configure the client with the' \
|
63
|
+
' required kms_key_id'
|
64
|
+
else
|
65
|
+
raise ArgumentError, 'Unsupported wrap-alg: ' \
|
66
|
+
"#{envelope['x-amz-wrap-alg']}"
|
67
|
+
end
|
68
|
+
iv = decode64(envelope['x-amz-iv'])
|
69
|
+
Utils.aes_decryption_cipher(:GCM, key, iv)
|
70
|
+
end
|
32
71
|
end
|
33
72
|
|
34
73
|
private
|
@@ -56,7 +95,6 @@ module Aws
|
|
56
95
|
def decode64(str)
|
57
96
|
Base64.decode64(str)
|
58
97
|
end
|
59
|
-
|
60
98
|
end
|
61
99
|
end
|
62
100
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'base64'
|
2
4
|
|
3
5
|
module Aws
|
@@ -10,6 +12,7 @@ module Aws
|
|
10
12
|
envelope, cipher = context[:encryption][:cipher_provider].encryption_cipher
|
11
13
|
apply_encryption_envelope(context, envelope, cipher)
|
12
14
|
apply_encryption_cipher(context, cipher)
|
15
|
+
apply_cse_user_agent(context)
|
13
16
|
@handler.call(context)
|
14
17
|
end
|
15
18
|
|
@@ -36,14 +39,22 @@ module Aws
|
|
36
39
|
context.params[:body] = IOEncrypter.new(cipher, io)
|
37
40
|
context.params[:metadata] ||= {}
|
38
41
|
context.params[:metadata]['x-amz-unencrypted-content-length'] = io.size
|
39
|
-
if
|
40
|
-
|
42
|
+
if context.params.delete(:content_md5)
|
43
|
+
warn('Setting content_md5 on client side encrypted objects is deprecated')
|
41
44
|
end
|
42
45
|
context.http_response.on_headers do
|
43
46
|
context.params[:body].close
|
44
47
|
end
|
45
48
|
end
|
46
49
|
|
50
|
+
def apply_cse_user_agent(context)
|
51
|
+
if context.config.user_agent_suffix.nil?
|
52
|
+
context.config.user_agent_suffix = EC_USER_AGENT
|
53
|
+
elsif !context.config.user_agent_suffix.include? EC_USER_AGENT
|
54
|
+
context.config.user_agent_suffix += " #{EC_USER_AGENT}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
47
58
|
end
|
48
59
|
end
|
49
60
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Aws
|
2
4
|
module S3
|
3
5
|
module Encryption
|
@@ -7,8 +9,10 @@ module Aws
|
|
7
9
|
# @param [OpenSSL::Cipher] cipher
|
8
10
|
# @param [IO#write] io An IO-like object that responds to `#write`.
|
9
11
|
def initialize(cipher, io)
|
10
|
-
@cipher = cipher
|
11
|
-
|
12
|
+
@cipher = cipher
|
13
|
+
# Ensure that IO is reset between retries
|
14
|
+
@io = io.tap { |io| io.truncate(0) if io.respond_to?(:truncate) }
|
15
|
+
@cipher_buffer = String.new
|
12
16
|
end
|
13
17
|
|
14
18
|
# @return [#write]
|
@@ -16,7 +20,11 @@ module Aws
|
|
16
20
|
|
17
21
|
def write(chunk)
|
18
22
|
# decrypt and write
|
19
|
-
@
|
23
|
+
if @cipher.method(:update).arity == 1
|
24
|
+
@io.write(@cipher.update(chunk))
|
25
|
+
else
|
26
|
+
@io.write(@cipher.update(chunk, @cipher_buffer))
|
27
|
+
end
|
20
28
|
end
|
21
29
|
|
22
30
|
def finalize
|