Skip to content

refactor: Remove keyring trace #291

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Aug 13, 2020
18 changes: 8 additions & 10 deletions src/aws_encryption_sdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ def encrypt(**kwargs):
When using this function, the entire ciphertext message is encrypted into memory before returning
any data. If streaming is desired, see :class:`aws_encryption_sdk.stream`.
.. versionadded:: 1.5.0
.. versionadded:: 2.0.0
The *keyring* parameter.
.. versionadded:: 1.5.0
.. versionadded:: 2.0.0
For backwards compatibility,
the new :class:`CryptoResult` return value also unpacks like a 2-member tuple.
Expand Down Expand Up @@ -80,16 +80,15 @@ def encrypt(**kwargs):
:param algorithm: Algorithm to use for encryption
:type algorithm: aws_encryption_sdk.identifiers.Algorithm
:param int frame_length: Frame length in bytes
:returns: Encrypted message, message metadata (header), and keyring trace
:returns: Encrypted message and message metadata (header)
:rtype: CryptoResult
"""
with StreamEncryptor(**kwargs) as encryptor:
ciphertext = encryptor.read()

header_copy = copy.deepcopy(encryptor.header)
keyring_trace_copy = copy.deepcopy(encryptor.keyring_trace)

return CryptoResult(result=ciphertext, header=header_copy, keyring_trace=keyring_trace_copy)
return CryptoResult(result=ciphertext, header=header_copy)


def decrypt(**kwargs):
Expand All @@ -99,10 +98,10 @@ def decrypt(**kwargs):
When using this function, the entire ciphertext message is decrypted into memory before returning
any data. If streaming is desired, see :class:`aws_encryption_sdk.stream`.
.. versionadded:: 1.5.0
.. versionadded:: 2.0.0
The *keyring* parameter.
.. versionadded:: 1.5.0
.. versionadded:: 2.0.0
For backwards compatibility,
the new :class:`CryptoResult` return value also unpacks like a 2-member tuple.
Expand Down Expand Up @@ -142,16 +141,15 @@ def decrypt(**kwargs):
:param int max_body_length: Maximum frame size (or content length for non-framed messages)
in bytes to read from ciphertext message.
:returns: Decrypted plaintext, message metadata (header), and keyring trace
:returns: Decrypted plaintext and message metadata (header)
:rtype: CryptoResult
"""
with StreamDecryptor(**kwargs) as decryptor:
plaintext = decryptor.read()

header_copy = copy.deepcopy(decryptor.header)
keyring_trace_copy = copy.deepcopy(decryptor.keyring_trace)

return CryptoResult(result=plaintext, header=header_copy, keyring_trace=keyring_trace_copy)
return CryptoResult(result=plaintext, header=header_copy)


def stream(**kwargs):
Expand Down
7 changes: 0 additions & 7 deletions src/aws_encryption_sdk/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,6 @@ class InvalidDataKeyError(AWSEncryptionSDKClientError):
"""Exception class for Invalid Data Keys."""


class InvalidKeyringTraceError(AWSEncryptionSDKClientError):
"""Exception class for invalid Keyring Traces.

.. versionadded:: 1.5.0
"""


class InvalidProviderIdError(AWSEncryptionSDKClientError):
"""Exception class for Invalid Provider IDs."""

Expand Down
25 changes: 0 additions & 25 deletions src/aws_encryption_sdk/identifiers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import struct
from enum import Enum

import attr
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec, padding, rsa
from cryptography.hazmat.primitives.ciphers import algorithms, modes
Expand Down Expand Up @@ -329,27 +328,3 @@ class ContentAADString(Enum):
FRAME_STRING_ID = b"AWSKMSEncryptionClient Frame"
FINAL_FRAME_STRING_ID = b"AWSKMSEncryptionClient Final Frame"
NON_FRAMED_STRING_ID = b"AWSKMSEncryptionClient Single Block"


class KeyringTraceFlag(Enum):
"""KeyRing Trace actions."""

@attr.s
class KeyringTraceFlagValue(object):
"""Keyring trace flags do not have defined serializable values."""

name = attr.ib()

#: A flag to represent that a keyring has generated a plaintext data key.
GENERATED_DATA_KEY = KeyringTraceFlagValue("GENERATED_DATA_KEY")
#: A flag to represent that a keyring has created an encrypted data key.
ENCRYPTED_DATA_KEY = KeyringTraceFlagValue("ENCRYPTED_DATA_KEY")
#: A flag to represent that a keyring has obtained
#: the corresponding plaintext data key from an encrypted data key.
DECRYPTED_DATA_KEY = KeyringTraceFlagValue("DECRYPTED_DATA_KEY")
#: A flag to represent that the keyring has cryptographically
#: bound the encryption context to a newly created encrypted data key.
SIGNED_ENCRYPTION_CONTEXT = KeyringTraceFlagValue("SIGNED_ENCRYPTION_CONTEXT")
#: A flag to represent that the keyring has verified that an encrypted
#: data key was originally created with a particular encryption context.
VERIFIED_ENCRYPTION_CONTEXT = KeyringTraceFlagValue("VERIFIED_ENCRYPTION_CONTEXT")
40 changes: 15 additions & 25 deletions src/aws_encryption_sdk/keyrings/aws_kms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# SPDX-License-Identifier: Apache-2.0
"""Keyring for use with AWS Key Management Service (KMS).

.. versionadded:: 1.5.0
.. versionadded:: 2.0.0

"""
import logging
Expand All @@ -17,7 +17,7 @@
from aws_encryption_sdk.keyrings.base import Keyring
from aws_encryption_sdk.keyrings.multi import MultiKeyring
from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials
from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, KeyringTraceFlag, MasterKeyInfo, RawDataKey
from aws_encryption_sdk.structures import EncryptedDataKey, MasterKeyInfo, RawDataKey

from .client_suppliers import DefaultClientSupplier

Expand All @@ -34,9 +34,6 @@
__all__ = ("AwsKmsKeyring", "KEY_NAMESPACE")

_LOGGER = logging.getLogger(__name__)
_GENERATE_FLAGS = {KeyringTraceFlag.GENERATED_DATA_KEY}
_ENCRYPT_FLAGS = {KeyringTraceFlag.ENCRYPTED_DATA_KEY, KeyringTraceFlag.SIGNED_ENCRYPTION_CONTEXT}
_DECRYPT_FLAGS = {KeyringTraceFlag.DECRYPTED_DATA_KEY, KeyringTraceFlag.VERIFIED_ENCRYPTION_CONTEXT}

#: Key namespace used for all encrypted data keys created by the KMS keyring.
KEY_NAMESPACE = "aws-kms"
Expand Down Expand Up @@ -78,7 +75,7 @@ class AwsKmsKeyring(Keyring):
.. _discovery mode:
https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/choose-keyring.html#kms-keyring-discovery

.. versionadded:: 1.5.0
.. versionadded:: 2.0.0

:param ClientSupplier client_supplier: Client supplier that provides AWS KMS clients (optional)
:param bool is_discovery: Should this be a discovery keyring (optional)
Expand Down Expand Up @@ -166,7 +163,7 @@ class _AwsKmsSingleCmkKeyring(Keyring):
This keyring should never be used directly.
It should only ever be used internally by :class:`AwsKmsKeyring`.

.. versionadded:: 1.5.0
.. versionadded:: 2.0.0

:param str key_id: CMK key ID
:param ClientSupplier client_supplier: Client supplier to use when asking for clients
Expand All @@ -182,7 +179,6 @@ class _AwsKmsSingleCmkKeyring(Keyring):

def on_encrypt(self, encryption_materials):
# type: (EncryptionMaterials) -> EncryptionMaterials
trace_info = MasterKeyInfo(provider_id=KEY_NAMESPACE, key_info=self._key_id)
new_materials = encryption_materials
try:
if new_materials.data_encryption_key is None:
Expand All @@ -193,10 +189,7 @@ def on_encrypt(self, encryption_materials):
algorithm=new_materials.algorithm,
grant_tokens=self._grant_tokens,
)
new_materials = new_materials.with_data_encryption_key(
data_encryption_key=plaintext_key,
keyring_trace=KeyringTrace(wrapping_key=trace_info, flags=_GENERATE_FLAGS),
)
new_materials = new_materials.with_data_encryption_key(data_encryption_key=plaintext_key)
else:
encrypted_key = _do_aws_kms_encrypt(
client_supplier=self._client_supplier,
Expand All @@ -207,13 +200,13 @@ def on_encrypt(self, encryption_materials):
)
except Exception: # pylint: disable=broad-except
# We intentionally WANT to catch all exceptions here
message = "Unable to generate or encrypt data key using {}".format(trace_info)
message = "Unable to generate or encrypt data key using {}".format(
MasterKeyInfo(provider_id=KEY_NAMESPACE, key_info=self._key_id)
)
_LOGGER.exception(message)
raise EncryptKeyError(message)

return new_materials.with_encrypted_data_key(
encrypted_data_key=encrypted_key, keyring_trace=KeyringTrace(wrapping_key=trace_info, flags=_ENCRYPT_FLAGS)
)
return new_materials.with_encrypted_data_key(encrypted_data_key=encrypted_key)

def on_decrypt(self, decryption_materials, encrypted_data_keys):
# type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials
Expand Down Expand Up @@ -244,7 +237,7 @@ class _AwsKmsDiscoveryKeyring(Keyring):
This keyring should never be used directly.
It should only ever be used internally by :class:`AwsKmsKeyring`.

.. versionadded:: 1.5.0
.. versionadded:: 2.0.0

:param ClientSupplier client_supplier: Client supplier to use when asking for clients
:param List[str] grant_tokens: AWS KMS grant tokens to include in requests (optional)
Expand Down Expand Up @@ -285,7 +278,7 @@ def _try_aws_kms_decrypt(client_supplier, decryption_materials, grant_tokens, en

Any errors encountered are caught and logged.

.. versionadded:: 1.5.0
.. versionadded:: 2.0.0

"""
try:
Expand All @@ -301,10 +294,7 @@ def _try_aws_kms_decrypt(client_supplier, decryption_materials, grant_tokens, en
_LOGGER.exception("Unable to decrypt encrypted data key from %s", encrypted_data_key.key_provider)
return decryption_materials

return decryption_materials.with_data_encryption_key(
data_encryption_key=plaintext_key,
keyring_trace=KeyringTrace(wrapping_key=encrypted_data_key.key_provider, flags=_DECRYPT_FLAGS),
)
return decryption_materials.with_data_encryption_key(data_encryption_key=plaintext_key)


def _do_aws_kms_decrypt(client_supplier, key_name, encrypted_data_key, encryption_context, grant_tokens):
Expand All @@ -313,7 +303,7 @@ def _do_aws_kms_decrypt(client_supplier, key_name, encrypted_data_key, encryptio

Any errors encountered are passed up the chain without comment.

.. versionadded:: 1.5.0
.. versionadded:: 2.0.0

"""
region = _region_from_key_id(encrypted_data_key.key_provider.key_info.decode("utf-8"))
Expand Down Expand Up @@ -360,7 +350,7 @@ def _do_aws_kms_generate_data_key(client_supplier, key_name, encryption_context,

Any errors encountered are passed up the chain without comment.

.. versionadded:: 1.5.0
.. versionadded:: 2.0.0

"""
region = _region_from_key_id(key_name)
Expand All @@ -383,7 +373,7 @@ def _region_from_key_id(key_id):

If the region cannot be found, ``None`` is returned instead.

.. versionadded:: 1.5.0
.. versionadded:: 2.0.0

"""
parts = key_id.split(":", 4)
Expand Down
45 changes: 9 additions & 36 deletions src/aws_encryption_sdk/keyrings/raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey, RSAPublicKey

from aws_encryption_sdk.exceptions import EncryptKeyError, GenerateKeyError
from aws_encryption_sdk.identifiers import EncryptionKeyType, KeyringTraceFlag, WrappingAlgorithm
from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm
from aws_encryption_sdk.internal.crypto.wrapping_keys import EncryptedData, WrappingKey
from aws_encryption_sdk.internal.formatting.deserialize import deserialize_wrapped_key
from aws_encryption_sdk.internal.formatting.serialize import serialize_raw_master_key_prefix, serialize_wrapped_key
from aws_encryption_sdk.key_providers.raw import RawMasterKey
from aws_encryption_sdk.keyrings.base import Keyring
from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials
from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey
from aws_encryption_sdk.structures import EncryptedDataKey, MasterKeyInfo, RawDataKey

try: # Python 3.5.0 and 3.5.1 have incompatible typing modules
from typing import Iterable # noqa pylint: disable=unused-import
Expand Down Expand Up @@ -55,23 +55,18 @@ def _generate_data_key(
_LOGGER.exception(error_message)
raise GenerateKeyError("Unable to generate data encryption key.")

# Create a keyring trace
keyring_trace = KeyringTrace(wrapping_key=key_provider, flags={KeyringTraceFlag.GENERATED_DATA_KEY})

# plaintext_data_key to RawDataKey
data_encryption_key = RawDataKey(key_provider=key_provider, data_key=plaintext_data_key)

return encryption_materials.with_data_encryption_key(
data_encryption_key=data_encryption_key, keyring_trace=keyring_trace
)
return encryption_materials.with_data_encryption_key(data_encryption_key=data_encryption_key,)


@attr.s
class RawAESKeyring(Keyring):
"""Generate an instance of Raw AES Keyring which encrypts using AES-GCM algorithm using wrapping key provided as a
byte array

.. versionadded:: 1.5.0
.. versionadded:: 2.0.0

:param str key_namespace: String defining the keyring.

Expand Down Expand Up @@ -175,13 +170,7 @@ def on_encrypt(self, encryption_materials):
_LOGGER.exception(error_message)
raise EncryptKeyError(error_message)

# Update Keyring Trace
keyring_trace = KeyringTrace(
wrapping_key=self._key_provider,
flags={KeyringTraceFlag.ENCRYPTED_DATA_KEY, KeyringTraceFlag.SIGNED_ENCRYPTION_CONTEXT},
)

return new_materials.with_encrypted_data_key(encrypted_data_key=encrypted_data_key, keyring_trace=keyring_trace)
return new_materials.with_encrypted_data_key(encrypted_data_key=encrypted_data_key)

def on_decrypt(self, decryption_materials, encrypted_data_keys):
# type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials
Expand Down Expand Up @@ -228,18 +217,10 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys):
# until it either succeeds or runs out of encrypted data keys.
continue

# Create a keyring trace
keyring_trace = KeyringTrace(
wrapping_key=self._key_provider,
flags={KeyringTraceFlag.DECRYPTED_DATA_KEY, KeyringTraceFlag.VERIFIED_ENCRYPTION_CONTEXT},
)

# Update decryption materials
data_encryption_key = RawDataKey(key_provider=self._key_provider, data_key=plaintext_data_key)

return new_materials.with_data_encryption_key(
data_encryption_key=data_encryption_key, keyring_trace=keyring_trace
)
return new_materials.with_data_encryption_key(data_encryption_key=data_encryption_key)

return new_materials

Expand All @@ -249,7 +230,7 @@ class RawRSAKeyring(Keyring):
"""Generate an instance of Raw RSA Keyring which performs asymmetric encryption and decryption using public
and private keys provided

.. versionadded:: 1.5.0
.. versionadded:: 2.0.0

:param str key_namespace: String defining the keyring ID

Expand Down Expand Up @@ -421,11 +402,8 @@ def on_encrypt(self, encryption_materials):
_LOGGER.exception(error_message)
raise EncryptKeyError(error_message)

# Update Keyring Trace
keyring_trace = KeyringTrace(wrapping_key=self._key_provider, flags={KeyringTraceFlag.ENCRYPTED_DATA_KEY})

# Add encrypted data key to encryption_materials
return new_materials.with_encrypted_data_key(encrypted_data_key=encrypted_data_key, keyring_trace=keyring_trace)
return new_materials.with_encrypted_data_key(encrypted_data_key=encrypted_data_key)

def on_decrypt(self, decryption_materials, encrypted_data_keys):
# type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials
Expand Down Expand Up @@ -465,14 +443,9 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys):
# until it either succeeds or runs out of encrypted data keys.
continue

# Create a keyring trace
keyring_trace = KeyringTrace(wrapping_key=self._key_provider, flags={KeyringTraceFlag.DECRYPTED_DATA_KEY})

# Update decryption materials
data_encryption_key = RawDataKey(key_provider=self._key_provider, data_key=plaintext_data_key)

return new_materials.with_data_encryption_key(
data_encryption_key=data_encryption_key, keyring_trace=keyring_trace
)
return new_materials.with_data_encryption_key(data_encryption_key=data_encryption_key)

return new_materials
Loading