Class: Aws::S3::EncryptionV3::Decryption Private
- Inherits:
-
Object
- Object
- Aws::S3::EncryptionV3::Decryption
- Defined in:
- lib/aws-sdk-s3/encryptionV3/decryption.rb
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
Constant Summary collapse
- ENVELOP_KEY =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
% - The mapkey “x-amz-3” MUST be present for V3 format objects.
../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
% - The mapkey “x-amz-w” MUST be present for V3 format objects.
../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
type=implication
% - This mapkey (“x-amz-3”) SHOULD be represented by a constant named “ENCRYPTED_DATA_KEY_V3” or similar in the implementation code.
../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
type=implication
% - This mapkey (“x-amz-w”) SHOULD be represented by a constant named “ENCRYPTED_DATA_KEY_ALGORITHM_V3” or similar in the implementation code.
%w[ x-amz-3 x-amz-w ].freeze
- OPTIONAL_ENVELOP_KEY =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
% - The mapkey “x-amz-m” SHOULD be present for V3 format objects that use Raw Keyring Material Description.
../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
% - The mapkey “x-amz-t” SHOULD be present for V3 format objects that use KMS Encryption Context.
../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
type=implication
% - This mapkey (“x-amz-m”) SHOULD be represented by a constant named “MAT_DESC_V3” or similar in the implementation code.
../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
type=implication
% - This mapkey (“x-amz-t”) SHOULD be represented by a constant named “ENCRYPTION_CONTEXT_V3” or similar in the implementation code.
%w[ x-amz-m x-amz-t ].freeze
- METADATA_KEY =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
% - The mapkey “x-amz-c” MUST be present for V3 format objects.
../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
% - The mapkey “x-amz-d” MUST be present for V3 format objects.
../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
% - The mapkey “x-amz-i” MUST be present for V3 format objects.
../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
type=implication
% - This mapkey (“x-amz-c”) SHOULD be represented by a constant named “CONTENT_CIPHER_V3” or similar in the implementation code.
../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
type=implication
% - This mapkey (“x-amz-d”) SHOULD be represented by a constant named “KEY_COMMITMENT_V3” or similar in the implementation code.
../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
type=implication
% - This mapkey (“x-amz-i”) SHOULD be represented by a constant named “MESSAGE_ID_V3” or similar in the implementation code.
%w[ x-amz-c x-amz-d x-amz-i ].freeze
- LEGACY_POSSIBLE_ENVELOPE_KEYS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Reference V2’s envelope keys rather than duplicating them
Aws::S3::EncryptionV2::Decryption::POSSIBLE_ENVELOPE_KEYS
- POSSIBLE_ENVELOPE_KEYS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
(ENVELOP_KEY + METADATA_KEY + OPTIONAL_ENVELOP_KEY + LEGACY_POSSIBLE_ENVELOPE_KEYS).uniq
- REQUIRED_ENVELOPE_KEYS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
(ENVELOP_KEY + METADATA_KEY).uniq
- POSSIBLE_WRAPPING_FORMATS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
%w[ 01 02 11 12 21 22 ].freeze
- POSSIBLE_ENCRYPTION_FORMATS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
%w[ 115 ].freeze
Class Method Summary collapse
- .complete_envelop?(possible_envelope) ⇒ Boolean private
- .decryption_cipher(context) ⇒ Object private
- .envelope_from_instr_file(context) ⇒ Object private
- .envelope_from_metadata(context) ⇒ Object private
-
.get_decrypter(context, cipher, _envelope) ⇒ Object
private
This method fetches the tag from the end of the object by making a GET Object w/range request.
- .get_encryption_envelope(context) ⇒ Object private
- .v3?(context) ⇒ Boolean private
- .v3_envelope?(possible_envelope) ⇒ Boolean private
Class Method Details
.complete_envelop?(possible_envelope) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/aws-sdk-s3/encryptionV3/decryption.rb', line 154 def complete_envelop?(possible_envelope) # V3 envelops always store some information in metadata # If we look at the metadata, we may still need to check the instruction file # Similarly, if we start checking the instruction file, # we sill need to get the message id and commitment key from the metadata envelop_count = ENVELOP_KEY.count { |key| possible_envelope.key?(key) } = METADATA_KEY.count { |key| possible_envelope.key?(key) } # If we have all keys, we are done (envelop_count == ENVELOP_KEY.size && == METADATA_KEY.size) || # If we have 0 keys, then this is done too. # Because it means we are not a v3 committing message. (envelop_count.zero? && .zero?) end |
.decryption_cipher(context) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/aws-sdk-s3/encryptionV3/decryption.rb', line 89 def decryption_cipher(context) if (envelope = get_encryption_envelope(context)) cipher = context[:encryption][:v3_cipher_provider] .decryption_cipher( envelope, context[:encryption] ) [cipher, envelope] else raise Errors::DecryptionError, 'unable to locate encryption envelope' end end |
.envelope_from_instr_file(context) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/aws-sdk-s3/encryptionV3/decryption.rb', line 188 def envelope_from_instr_file(context) suffix = context[:encryption][:instruction_file_suffix] possible_envelope = Json.load(context.client.get_object( bucket: context.params[:bucket], key: context.params[:key] + suffix ).body.read) unless (keys = possible_envelope.keys & METADATA_KEY).empty? msg = "unsupported metadata key found in instruction file: #{keys.join(', ')}" raise Errors::DecryptionError, msg end possible_envelope rescue S3::Errors::ServiceError, Json::ParseError nil end |
.envelope_from_metadata(context) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/aws-sdk-s3/encryptionV3/decryption.rb', line 169 def (context) POSSIBLE_ENVELOPE_KEYS.filter_map do |suffix| ##= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys ##= type=exception ##= reason=Ruby is reading the headers directly ##% The "x-amz-meta-" prefix is automatically added by the S3 server and MUST NOT be included in implementation code. if (value = context.http_response.headers["x-amz-meta-#{suffix}"]) ##= ../specification/s3-encryption/data-format/metadata-strategy.md#object-metadata ##= type=exception ##= reason=This has never been supported in Ruby ##% The S3EC SHOULD support decoding the S3 Server's "double encoding". ##= ../specification/s3-encryption/data-format/metadata-strategy.md#object-metadata ##% If the S3EC does not support decoding the S3 Server's "double encoding" then it MUST return the content metadata untouched. [suffix, value] end end.to_h end |
.get_decrypter(context, cipher, _envelope) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method fetches the tag from the end of the object by making a GET Object w/range request. This auth tag is used to initialize the cipher, and the decrypter truncates the auth tag from the body when writing the final bytes.
106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/aws-sdk-s3/encryptionV3/decryption.rb', line 106 def get_decrypter(context, cipher, _envelope) http_resp = context.http_response content_length = http_resp.headers['content-length'].to_i # The encrypted object contains both the cipher text # plus a trailing auth tag. # The trailing auth tag will be accumulated and added to the cipher.auth_tag. IOAuthDecrypter.new( io: http_resp.body, encrypted_content_length: content_length - AES_GCM_TAG_LEN_BYTES, cipher: cipher ) end |
.get_encryption_envelope(context) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/aws-sdk-s3/encryptionV3/decryption.rb', line 120 def get_encryption_envelope(context) # Get initial envelope data from :envelope_location envelope = if context[:encryption][:envelope_location] == :metadata (context) else envelope_from_instr_file(context) end # If empty or incomplete, get/merge data from secondary source ##= ../specification/s3-encryption/data-format/content-metadata.md#determining-s3ec-object-status ##% If the object matches none of the V1/V2/V3 formats, the S3EC MUST attempt to get the instruction file. if envelope.nil? || envelope.empty? || !complete_envelop?(envelope) secondary = if context[:encryption][:envelope_location] == :metadata envelope_from_instr_file(context) else (context) end # If we attempted to read a non-existent instruction file, # then envelope would be nil, # but we may find the information we need in the metadata. if envelope && secondary envelope.merge!(secondary) elsif secondary envelope = secondary end end ##= ../specification/s3-encryption/data-format/metadata-strategy.md#object-metadata ##% If the S3EC does not support decoding the S3 Server's "double encoding" then it MUST return the content metadata untouched. v3_envelope?(envelope) end |
.v3?(context) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
85 86 87 |
# File 'lib/aws-sdk-s3/encryptionV3/decryption.rb', line 85 def v3?(context) context.http_response.headers.key?('x-amz-meta-x-amz-i') end |
.v3_envelope?(possible_envelope) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/aws-sdk-s3/encryptionV3/decryption.rb', line 203 def v3_envelope?(possible_envelope) unless (keys = possible_envelope.keys & LEGACY_POSSIBLE_ENVELOPE_KEYS).empty? ##= ../specification/s3-encryption/data-format/content-metadata.md#determining-s3ec-object-status ##% If there are multiple mapkeys which are meant to be exclusive, such as "x-amz-key", "x-amz-key-v2", and "x-amz-3" then the S3EC SHOULD throw an exception. msg = "legacy metadata key found: #{keys.join(', ')}" raise Errors::DecryptionError, msg end unless POSSIBLE_ENCRYPTION_FORMATS.include? possible_envelope['x-amz-c'] alg = possible_envelope['x-amz-c'].inspect msg = "unsupported content encrypting key (cek) format: #{alg} #{possible_envelope.inspect}" raise Errors::DecryptionError, msg end unless POSSIBLE_WRAPPING_FORMATS.include? possible_envelope['x-amz-w'] alg = possible_envelope['x-amz-w'].inspect msg = "unsupported key wrapping algorithm: #{alg}" raise Errors::DecryptionError, msg end unless (missing_keys = REQUIRED_ENVELOPE_KEYS - possible_envelope.keys).empty? ##= ../specification/s3-encryption/data-format/content-metadata.md#determining-s3ec-object-status ##% In general, if there is any deviation from the above format, with the exception of additional unrelated mapkeys, then the S3EC SHOULD throw an exception. msg = "incomplete v3 encryption envelope:\n" msg += " missing: #{missing_keys.join(',')}\n" raise Errors::DecryptionError, msg end possible_envelope end |