Skip to content

Commit 952bce4

Browse files
authored
Refactor MasterKeyProvider.master_keys_for_data_key (#200)
* refactor MasterKeyProvider.decrypt_data_key and break out master key location to master_keys_for_data_key * simplify MasterKey.owns_data_key * autoformat * fix linting issues
1 parent a446f37 commit 952bce4

File tree

1 file changed

+57
-38
lines changed
  • src/aws_encryption_sdk/key_providers

1 file changed

+57
-38
lines changed

src/aws_encryption_sdk/key_providers/base.py

+57-38
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,17 @@
2626
MasterKeyProviderError,
2727
)
2828
from aws_encryption_sdk.internal.str_ops import to_bytes
29+
from aws_encryption_sdk.structures import DataKey # pylint: disable=unused-import
30+
from aws_encryption_sdk.structures import EncryptedDataKey # pylint: disable=unused-import
31+
from aws_encryption_sdk.structures import RawDataKey # pylint: disable=unused-import
2932
from aws_encryption_sdk.structures import MasterKeyInfo
3033

34+
try: # Python 3.5.0 and 3.5.1 have incompatible typing modules
35+
from typing import Iterable, Union # noqa pylint: disable=unused-import
36+
except ImportError: # pragma: no cover
37+
# We only actually need these imports when running the mypy checks
38+
pass
39+
3140
_LOGGER = logging.getLogger(__name__)
3241

3342

@@ -212,6 +221,35 @@ def master_key_for_decrypt(self, key_info):
212221
self._decrypt_key_index[key_info] = decrypt_master_key
213222
return decrypt_master_key
214223

224+
def master_keys_for_data_key(self, data_key):
225+
# type: (Union[DataKey, EncryptedDataKey, RawDataKey]) -> Iterable[MasterKey]
226+
"""Locates the correct master keys from children for the specified data key.
227+
228+
:param data_key: Data key for which to locate owning master keys
229+
:type data_key: :class:`EncryptedDataKey`, :class:`RawDataKey`, or :class:`DataKey`
230+
:returns: Masters key that own data key
231+
:rtype: iterator of :class:`MasterKey`
232+
:raises UnknownIdentityError: if unable to locate the correct master key
233+
"""
234+
for member in [self] + self._members:
235+
if member.provider_id != data_key.key_provider.provider_id:
236+
continue
237+
238+
_LOGGER.debug("attempting to locate master key from key provider: %s", member.provider_id)
239+
240+
if isinstance(member, MasterKey):
241+
if member.owns_data_key(data_key):
242+
_LOGGER.debug("using existing master key")
243+
yield member
244+
245+
if self.vend_masterkey_on_decrypt:
246+
try:
247+
_LOGGER.debug("attempting to add master key: %s", data_key.key_provider.key_info)
248+
yield member.master_key_for_decrypt(data_key.key_provider.key_info)
249+
except InvalidKeyIdError:
250+
_LOGGER.debug("master key %s not available in provider", data_key.key_provider.key_info)
251+
continue
252+
215253
def decrypt_data_key(self, encrypted_data_key, algorithm, encryption_context):
216254
"""Iterates through all currently added Master Keys and Master Key Providers
217255
to attempt to decrypt data key.
@@ -225,42 +263,25 @@ def decrypt_data_key(self, encrypted_data_key, algorithm, encryption_context):
225263
:rtype: aws_encryption_sdk.structures.DataKey
226264
:raises DecryptKeyError: if unable to decrypt encrypted data key
227265
"""
228-
data_key = None
229-
master_key = None
230266
_LOGGER.debug("starting decrypt data key attempt")
231-
for member in [self] + self._members:
232-
if member.provider_id == encrypted_data_key.key_provider.provider_id:
233-
_LOGGER.debug("attempting to locate master key from key provider: %s", member.provider_id)
234-
if isinstance(member, MasterKey):
235-
_LOGGER.debug("using existing master key")
236-
master_key = member
237-
elif self.vend_masterkey_on_decrypt:
238-
try:
239-
_LOGGER.debug("attempting to add master key: %s", encrypted_data_key.key_provider.key_info)
240-
master_key = member.master_key_for_decrypt(encrypted_data_key.key_provider.key_info)
241-
except InvalidKeyIdError:
242-
_LOGGER.debug(
243-
"master key %s not available in provider", encrypted_data_key.key_provider.key_info
244-
)
245-
continue
246-
else:
247-
continue
248-
try:
249-
_LOGGER.debug(
250-
"attempting to decrypt data key with provider %s", encrypted_data_key.key_provider.key_info
251-
)
252-
data_key = master_key.decrypt_data_key(encrypted_data_key, algorithm, encryption_context)
253-
except (IncorrectMasterKeyError, DecryptKeyError) as error:
254-
_LOGGER.debug(
255-
"%s raised when attempting to decrypt data key with master key %s",
256-
repr(error),
257-
master_key.key_provider,
258-
)
259-
continue
260-
break # If this point is reached without throwing any errors, the data key has been decrypted
261-
if not data_key:
262-
raise DecryptKeyError("Unable to decrypt data key")
263-
return data_key
267+
for master_key in self.master_keys_for_data_key(encrypted_data_key):
268+
try:
269+
_LOGGER.debug(
270+
"attempting to decrypt data key with provider %s", encrypted_data_key.key_provider.key_info
271+
)
272+
return master_key.decrypt_data_key(encrypted_data_key, algorithm, encryption_context)
273+
274+
# MasterKeyProvider.decrypt_data_key throws DecryptKeyError
275+
# but MasterKey.decrypt_data_key throws IncorrectMasterKeyError
276+
except (IncorrectMasterKeyError, DecryptKeyError) as error:
277+
_LOGGER.debug(
278+
"%s raised when attempting to decrypt data key with master key %s",
279+
repr(error),
280+
master_key.key_provider,
281+
)
282+
continue
283+
284+
raise DecryptKeyError("Unable to decrypt data key")
264285

265286
def decrypt_data_key_from_list(self, encrypted_data_keys, algorithm, encryption_context):
266287
"""Receives a list of encrypted data keys and returns the first one which this provider is able to decrypt.
@@ -356,9 +377,7 @@ def owns_data_key(self, data_key):
356377
:returns: Boolean statement of ownership
357378
:rtype: bool
358379
"""
359-
if data_key.key_provider == self.key_provider:
360-
return True
361-
return False
380+
return data_key.key_provider == self.key_provider
362381

363382
def master_keys_for_encryption(self, encryption_context, plaintext_rostream, plaintext_length=None):
364383
"""Returns self and a list containing self, to match the format of output for a Master Key Provider.

0 commit comments

Comments
 (0)