aws-sdk-resources 2.3.12 → 2.3.13

Sign up to get free protection for your applications and to get access to all the features.
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