Skip to content

Commit

Permalink
refactor: Remove keyring trace (#291)
Browse files Browse the repository at this point in the history
* refactor: Remove keyring trace

* chore: run autoformat

* chore: Make linters happy

* Update src/aws_encryption_sdk/__init__.py

Co-authored-by: Matt Bullock <bullocm@amazon.com>

* Update src/aws_encryption_sdk/__init__.py

Co-authored-by: Matt Bullock <bullocm@amazon.com>

* Update src/aws_encryption_sdk/keyrings/aws_kms/__init__.py

Co-authored-by: Matt Bullock <bullocm@amazon.com>

* Update src/aws_encryption_sdk/keyrings/aws_kms/__init__.py

Co-authored-by: Matt Bullock <bullocm@amazon.com>

* Apply suggestions from code review

Co-authored-by: Matt Bullock <bullocm@amazon.com>

Co-authored-by: Matt Bullock <bullocm@amazon.com>
  • Loading branch information
MatthewBennington and mattsb42-aws committed Aug 13, 2020
1 parent 4705fa5 commit 0d21816
Show file tree
Hide file tree
Showing 19 changed files with 98 additions and 667 deletions.
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

0 comments on commit 0d21816

Please sign in to comment.