aws-sdk-resources 2.3.12 → 2.3.13

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 76114a5d01dbe1f0181019ddb59cd107b2ac8e03
4
- data.tar.gz: abcb08becd617abd22eaf6227185f9b27ec5b043
3
+ metadata.gz: 11c22ca5443cb742557f0ff0d51e1fef0df79fcf
4
+ data.tar.gz: e4491cd6fc35298e073d7a8b2acc125d51b1f4ff
5
5
  SHA512:
6
- metadata.gz: 789c7eef7377f560a950459011e3894c1bb21513540c3f3ae1a16eda3334892034eea17430ee45f75cbade0921519d2e0741bbfd84eaf6ea2567c8e43fa03a35
7
- data.tar.gz: c1b29ca6bb7dea3b4175fc6395c8768e9f306574fd84c56e2ee1a722ca6a1d821ede54936871552e3702f32dc82f0d4ff764472703a33406efe953e8e041bcfa
6
+ metadata.gz: 415203dbe9f34837a545a8665a75c2573ff78bdbce65fb04556fed2d8168b9144b7e7d8205334e3aac2cfa3d544d4c29cd5b9a4ef12cc1a10c5621f832cd9817
7
+ data.tar.gz: de05df3ec9627f3f6a53b9e41914921ec0476fd22702bf8a15736c53673ad13fe222c7c7c7b9e456dcf23bd5e2477043707793aaadd0583e3a9990b4cd77d932
@@ -9,6 +9,7 @@ module Aws
9
9
  autoload :EncryptHandler, 'aws-sdk-resources/services/s3/encryption/encrypt_handler'
10
10
  autoload :Errors, 'aws-sdk-resources/services/s3/encryption/errors'
11
11
  autoload :IOEncrypter, 'aws-sdk-resources/services/s3/encryption/io_encrypter'
12
+ autoload :IOAuthDecrypter, 'aws-sdk-resources/services/s3/encryption/io_auth_decrypter'
12
13
  autoload :IODecrypter, 'aws-sdk-resources/services/s3/encryption/io_decrypter'
13
14
  autoload :KeyProvider, 'aws-sdk-resources/services/s3/encryption/key_provider'
14
15
  autoload :KmsCipherProvider, 'aws-sdk-resources/services/s3/encryption/kms_cipher_provider'
@@ -22,6 +22,11 @@ module Aws
22
22
 
23
23
  POSSIBLE_ENVELOPE_KEYS = (V1_ENVELOPE_KEYS + V2_ENVELOPE_KEYS).uniq
24
24
 
25
+ POSSIBLE_ENCRYPTION_FORMATS = %w(
26
+ AES/GCM/NoPadding
27
+ AES/CBC/PKCS5Padding
28
+ )
29
+
25
30
  def call(context)
26
31
  attach_http_event_listeners(context)
27
32
  @handler.call(context)
@@ -30,10 +35,13 @@ module Aws
30
35
  private
31
36
 
32
37
  def attach_http_event_listeners(context)
38
+
33
39
  context.http_response.on_headers(200) do
34
40
  cipher = decryption_cipher(context)
35
- body = context.http_response.body
36
- context.http_response.body = IODecrypter.new(cipher, body)
41
+ decrypter = body_contains_auth_tag?(context) ?
42
+ authenticated_decrypter(context, cipher) :
43
+ IODecrypter.new(cipher, context.http_response.body)
44
+ context.http_response.body = decrypter
37
45
  end
38
46
 
39
47
  context.http_response.on_success(200) do
@@ -44,7 +52,7 @@ module Aws
44
52
  end
45
53
 
46
54
  context.http_response.on_error do
47
- if context.http_response.body.is_a?(IODecrypter)
55
+ if context.http_response.body.respond_to?(:io)
48
56
  context.http_response.body = context.http_response.body.io
49
57
  end
50
58
  end
@@ -103,7 +111,7 @@ module Aws
103
111
  end
104
112
 
105
113
  def v2_envelope(envelope)
106
- unless envelope['x-amz-cek-alg'] == 'AES/CBC/PKCS5Padding'
114
+ unless POSSIBLE_ENCRYPTION_FORMATS.include? envelope['x-amz-cek-alg']
107
115
  alg = envelope['x-amz-cek-alg'].inspect
108
116
  msg = "unsupported content encrypting key (cek) format: #{alg}"
109
117
  raise Errors::DecryptionError, msg
@@ -124,6 +132,42 @@ module Aws
124
132
  envelope
125
133
  end
126
134
 
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
+ # This method fetches the tag from the end of the object by
140
+ # making a GET Object w/range request. This auth tag is used
141
+ # to initialize the cipher, and the decrypter truncates the
142
+ # auth tag from the body when writing the final bytes.
143
+ def authenticated_decrypter(context, cipher)
144
+ http_resp = context.http_response
145
+ content_length = http_resp.headers['content-length'].to_i
146
+ auth_tag_length = http_resp.headers['x-amz-meta-x-amz-tag-len']
147
+ auth_tag_length = auth_tag_length.to_i / 8
148
+
149
+ auth_tag = context.client.get_object(
150
+ bucket: context.params[:bucket],
151
+ key: context.params[:key],
152
+ range: "bytes=-#{auth_tag_length}"
153
+ ).body.read
154
+
155
+ cipher.auth_tag = auth_tag
156
+ cipher.auth_data = ''
157
+
158
+ # The encrypted object contains both the cipher text
159
+ # plus a trailing auth tag. This decrypter will the body
160
+ # expect for the trailing auth tag.
161
+ decrypter = IOAuthDecrypter.new(
162
+ io: http_resp.body,
163
+ encrypted_content_length: content_length - auth_tag_length,
164
+ cipher: cipher)
165
+ end
166
+
167
+ def body_contains_auth_tag?(context)
168
+ context.http_response.headers['x-amz-meta-x-amz-tag-len']
169
+ end
170
+
127
171
  end
128
172
  end
129
173
  end
@@ -0,0 +1,50 @@
1
+ module Aws
2
+ module S3
3
+ module Encryption
4
+ # @api private
5
+ class IOAuthDecrypter
6
+
7
+ # @option options [required, IO#write] :io
8
+ # An IO-like object that responds to {#write}.
9
+ # @option options [required, Integer] :encrypted_content_length
10
+ # The number of bytes to decrypt from the `:io` object.
11
+ # This should be the total size of `:io` minus the length of
12
+ # the cipher auth tag.
13
+ # @option options [required, OpenSSL::Cipher] :cipher An initialized
14
+ # cipher that can be used to decrypt the bytes as they are
15
+ # written to the `:io` object. The cipher should already have
16
+ # its `#auth_tag` set.
17
+ def initialize(options = {})
18
+ @decrypter = IODecrypter.new(options[:cipher], options[:io])
19
+ @max_bytes = options[:encrypted_content_length]
20
+ @bytes_written = 0
21
+ end
22
+
23
+ def write(chunk)
24
+ chunk = truncate_chunk(chunk)
25
+ @bytes_written += chunk.bytesize
26
+ @decrypter.write(chunk)
27
+ end
28
+
29
+ def finalize
30
+ @decrypter.finalize
31
+ end
32
+
33
+ def io
34
+ @decrypter.io
35
+ end
36
+
37
+ private
38
+
39
+ def truncate_chunk(chunk)
40
+ if chunk.bytesize + @bytes_written <= @max_bytes
41
+ chunk
42
+ else
43
+ chunk[0..(@max_bytes - @bytes_written - 1)]
44
+ end
45
+ end
46
+
47
+ end
48
+ end
49
+ end
50
+ end
@@ -5,18 +5,17 @@ module Aws
5
5
  class IODecrypter
6
6
 
7
7
  # @param [OpenSSL::Cipher] cipher
8
- # @param [#write] io An IO-like object that responds to {#write}.
8
+ # @param [IO#write] io An IO-like object that responds to `#write`.
9
9
  def initialize(cipher, io)
10
- @orig_cipher = cipher.clone
11
10
  @cipher = cipher.clone
12
11
  @io = io
13
- reset_cipher
14
12
  end
15
13
 
16
14
  # @return [#write]
17
15
  attr_reader :io
18
16
 
19
17
  def write(chunk)
18
+ # decrypt and write
20
19
  @io.write(@cipher.update(chunk))
21
20
  end
22
21
 
@@ -24,12 +23,6 @@ module Aws
24
23
  @io.write(@cipher.final)
25
24
  end
26
25
 
27
- private
28
-
29
- def reset_cipher
30
- @cipher = @orig_cipher.clone
31
- end
32
-
33
26
  end
34
27
  end
35
28
  end
@@ -41,7 +41,18 @@ module Aws
41
41
  encryption_context: encryption_context,
42
42
  ).plaintext
43
43
  iv = decode64(envelope['x-amz-iv'])
44
- Utils.aes_decryption_cipher(:CBC, key, iv)
44
+ block_mode =
45
+ case envelope['x-amz-cek-alg']
46
+ when 'AES/CBC/PKCS5Padding'
47
+ :CBC
48
+ when 'AES/GCM/NoPadding'
49
+ :GCM
50
+ else
51
+ type = envelope['x-amz-cek-alg'].inspect
52
+ msg = "unsupported content encrypting key (cek) format: #{type}"
53
+ raise Errors::DecryptionError, msg
54
+ end
55
+ Utils.aes_decryption_cipher(block_mode, key, iv)
45
56
  end
46
57
 
47
58
  private
@@ -57,8 +57,8 @@ module Aws
57
57
  # @param [String, nil] iv The initialization vector
58
58
  def aes_cipher(mode, block_mode, key, iv)
59
59
  cipher = key ?
60
- OpenSSL::Cipher.new("AES-#{cipher_size(key)}-#{block_mode}") :
61
- OpenSSL::Cipher.new("AES-256-#{block_mode}")
60
+ OpenSSL::Cipher.new("aes-#{cipher_size(key)}-#{block_mode.downcase}") :
61
+ OpenSSL::Cipher.new("aes-256-#{block_mode.downcase}")
62
62
  cipher.send(mode) # encrypt or decrypt
63
63
  cipher.key = key if key
64
64
  cipher.iv = iv if iv
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws-sdk-resources
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.12
4
+ version: 2.3.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amazon Web Services
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-07 00:00:00.000000000 Z
11
+ date: 2016-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-core
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 2.3.12
19
+ version: 2.3.13
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 2.3.12
26
+ version: 2.3.13
27
27
  description: Provides resource oriented interfaces and other higher-level abstractions
28
28
  for many AWS services. This gem is part of the official AWS SDK for Ruby.
29
29
  email:
@@ -65,6 +65,7 @@ files:
65
65
  - lib/aws-sdk-resources/services/s3/encryption/default_key_provider.rb
66
66
  - lib/aws-sdk-resources/services/s3/encryption/encrypt_handler.rb
67
67
  - lib/aws-sdk-resources/services/s3/encryption/errors.rb
68
+ - lib/aws-sdk-resources/services/s3/encryption/io_auth_decrypter.rb
68
69
  - lib/aws-sdk-resources/services/s3/encryption/io_decrypter.rb
69
70
  - lib/aws-sdk-resources/services/s3/encryption/io_encrypter.rb
70
71
  - lib/aws-sdk-resources/services/s3/encryption/key_provider.rb