# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
"""Cryptographic materials provider to use ephemeral content encryption keys wrapped by delegated keys."""
from typing import Dict, Optional, Text
import attr
import six
from dynamodb_encryption_sdk.delegated_keys import DelegatedKey
from dynamodb_encryption_sdk.exceptions import UnwrappingError, WrappingError
from dynamodb_encryption_sdk.internal.validators import dictionary_validator
from dynamodb_encryption_sdk.materials.wrapped import WrappedCryptographicMaterials
from dynamodb_encryption_sdk.structures import EncryptionContext # noqa pylint: disable=unused-import
from . import CryptographicMaterialsProvider
__all__ = ("WrappedCryptographicMaterialsProvider",)
[docs]@attr.s(init=False)
class WrappedCryptographicMaterialsProvider(CryptographicMaterialsProvider):
"""Cryptographic materials provider to use ephemeral content encryption keys wrapped by delegated keys.
:param DelegatedKey signing_key: Delegated key used as signing and verification key
:param DelegatedKey wrapping_key: Delegated key used to wrap content key
.. note::
``wrapping_key`` must be provided if providing encryption materials
:param DelegatedKey unwrapping_key: Delegated key used to unwrap content key
.. note::
``unwrapping_key`` must be provided if providing decryption materials or loading
materials from material description
"""
_signing_key = attr.ib(validator=attr.validators.instance_of(DelegatedKey))
_wrapping_key = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(DelegatedKey)), default=None)
_unwrapping_key = attr.ib(
validator=attr.validators.optional(attr.validators.instance_of(DelegatedKey)), default=None
)
_material_description = attr.ib(
validator=attr.validators.optional(dictionary_validator(six.string_types, six.string_types)),
default=attr.Factory(dict),
)
def __init__(
self,
signing_key, # type: DelegatedKey
wrapping_key=None, # type: Optional[DelegatedKey]
unwrapping_key=None, # type: Optional[DelegatedKey]
material_description=None, # type: Optional[Dict[Text, Text]]
): # noqa=D107
# type: (...) -> None
# Workaround pending resolution of attrs/mypy interaction.
# https://github.com/python/mypy/issues/2088
# https://github.com/python-attrs/attrs/issues/215
if material_description is None:
material_description = {}
self._signing_key = signing_key
self._wrapping_key = wrapping_key
self._unwrapping_key = unwrapping_key
self._material_description = material_description
attr.validate(self)
def _build_materials(self, encryption_context):
# type: (EncryptionContext) -> WrappedCryptographicMaterials
"""Construct
:param EncryptionContext encryption_context: Encryption context for request
:returns: Wrapped cryptographic materials
:rtype: WrappedCryptographicMaterials
"""
material_description = self._material_description.copy()
material_description.update(encryption_context.material_description)
return WrappedCryptographicMaterials(
wrapping_key=self._wrapping_key,
unwrapping_key=self._unwrapping_key,
signing_key=self._signing_key,
material_description=material_description,
)
[docs] def encryption_materials(self, encryption_context):
# type: (EncryptionContext) -> WrappedCryptographicMaterials
"""Provide encryption materials.
:param EncryptionContext encryption_context: Encryption context for request
:returns: Encryption materials
:rtype: WrappedCryptographicMaterials
:raises WrappingError: if no wrapping key is available
"""
if self._wrapping_key is None:
raise WrappingError("Encryption materials cannot be provided: no wrapping key")
return self._build_materials(encryption_context)
[docs] def decryption_materials(self, encryption_context):
# type: (EncryptionContext) -> WrappedCryptographicMaterials
"""Provide decryption materials.
:param EncryptionContext encryption_context: Encryption context for request
:returns: Decryption materials
:rtype: WrappedCryptographicMaterials
:raises UnwrappingError: if no unwrapping key is available
"""
if self._unwrapping_key is None:
raise UnwrappingError("Decryption materials cannot be provided: no unwrapping key")
return self._build_materials(encryption_context)