From 0d2963176e4b3d4d298876189870fd7f6fbc848e Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 18 Jun 2019 14:07:50 -0700 Subject: [PATCH 001/110] Adding Keyring API --- src/aws_encryption_sdk/keyring/__init__.py | 13 ++++++ src/aws_encryption_sdk/keyring/base.py | 40 +++++++++++++++++++ src/aws_encryption_sdk/keyring/raw_keyring.py | 0 3 files changed, 53 insertions(+) create mode 100644 src/aws_encryption_sdk/keyring/__init__.py create mode 100644 src/aws_encryption_sdk/keyring/base.py create mode 100644 src/aws_encryption_sdk/keyring/raw_keyring.py diff --git a/src/aws_encryption_sdk/keyring/__init__.py b/src/aws_encryption_sdk/keyring/__init__.py new file mode 100644 index 000000000..b9037ea16 --- /dev/null +++ b/src/aws_encryption_sdk/keyring/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2019 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. +"""All provided keyrings.""" diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py new file mode 100644 index 000000000..0d6b9000c --- /dev/null +++ b/src/aws_encryption_sdk/keyring/base.py @@ -0,0 +1,40 @@ +# Copyright 2017 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. +"""Base class interface for Keyrings.""" + + +class Keyring(object): + def on_encrypt(self, encryption_materials): + """Generates a data key and encrypts it using all wrapping keys the Keyring is associated with. + + :param encryption_materials: Contains signing key, encryption context and algorithm suite + required to encrypt data key + :type : aws_encryption_sdk.materials_managers.EncryptionMaterials + :returns encryption_materials: Contains signing key, unencrypted data key, encrypted data keys, + encryption context and algorithm suite required to encrypt data key + :rtype : aws_encryption_sdk.materials_managers.EncryptionMaterials + :raises AttributeError: if encryption materials not available + """ + raise NotImplementedError("Keyring does not implement on_encrypt function") + + def on_decrypt(self, decryption_materials): + """Tries to decrypt one of the keys in the list of encrypted data keys using wrapping keys + the Keyring is associated with. + + :param decryption_materials: Contains verification key, list of encrypted data keys. + :type : aws_encryption_sdk.materials_managers.DecryptionMaterials + :returns decryption_materials: Contains verification key, list of encrypted data keys and decrypted data key. + :rtype : aws_encryption_sdk.materials_managers.DecryptionMaterials + :raises AttributeError: if decryption materials not available + """ + raise NotImplementedError("Keyring does not implement on_decrypt function") diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py new file mode 100644 index 000000000..e69de29bb From 237a2af41266312a6bd0a374f683395e31b169c3 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 18 Jun 2019 14:51:28 -0700 Subject: [PATCH 002/110] Added docstring to public class --- src/aws_encryption_sdk/keyring/base.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index 0d6b9000c..575758edd 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -14,6 +14,8 @@ class Keyring(object): + """Parent interface for Keyring classes. + """ def on_encrypt(self, encryption_materials): """Generates a data key and encrypts it using all wrapping keys the Keyring is associated with. From 9bbdf835e40522a39581d20fbc780463f302f2e6 Mon Sep 17 00:00:00 2001 From: MeghaShetty Date: Tue, 18 Jun 2019 14:12:41 -0700 Subject: [PATCH 003/110] Delete __init__.py --- src/aws_encryption_sdk/keyring/__init__.py | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 src/aws_encryption_sdk/keyring/__init__.py diff --git a/src/aws_encryption_sdk/keyring/__init__.py b/src/aws_encryption_sdk/keyring/__init__.py deleted file mode 100644 index b9037ea16..000000000 --- a/src/aws_encryption_sdk/keyring/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2019 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. -"""All provided keyrings.""" From 1a14a3b82af0891b2190f294309b7573904dfd67 Mon Sep 17 00:00:00 2001 From: MeghaShetty Date: Tue, 18 Jun 2019 14:12:53 -0700 Subject: [PATCH 004/110] Delete raw_keyring.py --- src/aws_encryption_sdk/keyring/raw_keyring.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/aws_encryption_sdk/keyring/raw_keyring.py diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py deleted file mode 100644 index e69de29bb..000000000 From c1a1c77e7c5a11f21825d3acb5c4be54e9247d1d Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 18 Jun 2019 15:36:18 -0700 Subject: [PATCH 005/110] Edited docstring --- src/aws_encryption_sdk/keyring/base.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index 575758edd..a1e77e905 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -16,6 +16,7 @@ class Keyring(object): """Parent interface for Keyring classes. """ + def on_encrypt(self, encryption_materials): """Generates a data key and encrypts it using all wrapping keys the Keyring is associated with. From 66b348f45f4edba14c313c8d315ca7da8286380f Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 18 Jun 2019 16:07:06 -0700 Subject: [PATCH 006/110] Edited docstring again --- src/aws_encryption_sdk/keyring/base.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index a1e77e905..88e3ae068 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -14,8 +14,7 @@ class Keyring(object): - """Parent interface for Keyring classes. - """ + """Parent interface for Keyring classes.""" def on_encrypt(self, encryption_materials): """Generates a data key and encrypts it using all wrapping keys the Keyring is associated with. From 4a0a1c6dcc1cd828f2e63fafdca95a0bc4d82725 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Wed, 19 Jun 2019 12:58:14 -0700 Subject: [PATCH 007/110] Changes in docstring statements --- src/aws_encryption_sdk/keyring/__init__.py | 13 ++++ src/aws_encryption_sdk/keyring/base.py | 5 +- src/aws_encryption_sdk/keyring/raw_keyring.py | 74 +++++++++++++++++++ 3 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 src/aws_encryption_sdk/keyring/__init__.py create mode 100644 src/aws_encryption_sdk/keyring/raw_keyring.py diff --git a/src/aws_encryption_sdk/keyring/__init__.py b/src/aws_encryption_sdk/keyring/__init__.py new file mode 100644 index 000000000..ada03b4d7 --- /dev/null +++ b/src/aws_encryption_sdk/keyring/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2017 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. +"""All provided Keyrings.""" diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index 88e3ae068..19f2ae169 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -17,7 +17,7 @@ class Keyring(object): """Parent interface for Keyring classes.""" def on_encrypt(self, encryption_materials): - """Generates a data key and encrypts it using all wrapping keys the Keyring is associated with. + """Generate a data key and encrypt it using all wrapping keys the Keyring is associated with. :param encryption_materials: Contains signing key, encryption context and algorithm suite required to encrypt data key @@ -30,8 +30,7 @@ def on_encrypt(self, encryption_materials): raise NotImplementedError("Keyring does not implement on_encrypt function") def on_decrypt(self, decryption_materials): - """Tries to decrypt one of the keys in the list of encrypted data keys using wrapping keys - the Keyring is associated with. + """Attempt to decrypt the encrypted data keys. :param decryption_materials: Contains verification key, list of encrypted data keys. :type : aws_encryption_sdk.materials_managers.DecryptionMaterials diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py new file mode 100644 index 000000000..30d2bbd5a --- /dev/null +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -0,0 +1,74 @@ +# Copyright 2017 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. +"""Resources required for Raw Keyrings.""" +import os +import attr + +import aws_encryption_sdk.internal.formatting.deserialize +import aws_encryption_sdk.internal.formatting.serialize +from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey +from aws_encryption_sdk.keyring.base import Keyring +from aws_encryption_sdk.structures import DataKey, RawDataKey + + +class RawAESKeyring(Keyring): + """Public class for Raw AES Keyring.""" + + def on_encrypt(self, encryption_materials): + # Generate data key + plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) + + # Encrypt data key + wrapping_key = attr.ib(hash=True, validator=attr.validators.instance_of(WrappingKey)) + encrypted_wrapped_key = wrapping_key.encrypt( + plaintext_data_key=plaintext_data_key, + encryption_context=encryption_materials.encryption_context + ) + encrypted_data_key = aws_encryption_sdk.internal.formatting.serialize.serialize_wrapped_key( + # WHAAAAT + key_provider=self.key_provider, + wrapping_algorithm=wrapping_key.wrapping_algorithm, + # WHAAAAT + wrapping_key_id=self.key_id, + encrypted_wrapped_key=encrypted_wrapped_key, + ) + + # Update keyring trace + + # Update encryption materials + encryption_materials.data_encryption_key = RawDataKey( + # WHAAAAT + key_provider=self.key_provider, + data_key=plaintext_data_key + ) + encryption_materials.encrypted_data_keys.add(encrypted_data_key) + + return encryption_materials + + def on_decrypt(self, decryption_materials): + # Decrypt data key + + + # Update keyring trace + + return decryption_materials + + +class RawRSAKeyring(Keyring): + """Public class for Raw RSA Keyring.""" + + def on_encrypt(self, encryption_materials): + return encryption_materials + + def on_decrypt(self, decryption_materials): + return decryption_materials From 5f6fcb958274da6109a6ccdab8b3fae010c21fdf Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Wed, 19 Jun 2019 13:06:19 -0700 Subject: [PATCH 008/110] Docstring changes --- src/aws_encryption_sdk/keyring/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index 19f2ae169..cdec0842a 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -17,7 +17,7 @@ class Keyring(object): """Parent interface for Keyring classes.""" def on_encrypt(self, encryption_materials): - """Generate a data key and encrypt it using all wrapping keys the Keyring is associated with. + """Generate a data key if not present and encrypt it using any available wrapping key. :param encryption_materials: Contains signing key, encryption context and algorithm suite required to encrypt data key From 9d8d96407e69229985625e16caaff72e3630c774 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 20 Jun 2019 13:53:32 -0700 Subject: [PATCH 009/110] Changes in docstring --- src/aws_encryption_sdk/keyring/base.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index cdec0842a..3c4689d70 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -21,11 +21,11 @@ def on_encrypt(self, encryption_materials): :param encryption_materials: Contains signing key, encryption context and algorithm suite required to encrypt data key - :type : aws_encryption_sdk.materials_managers.EncryptionMaterials - :returns encryption_materials: Contains signing key, unencrypted data key, encrypted data keys, + :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials + :returns: Contains signing key, unencrypted data key, encrypted data keys, encryption context and algorithm suite required to encrypt data key - :rtype : aws_encryption_sdk.materials_managers.EncryptionMaterials - :raises AttributeError: if encryption materials not available + :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials + :raises NotImplementedError: if method is not implemented """ raise NotImplementedError("Keyring does not implement on_encrypt function") @@ -33,9 +33,9 @@ def on_decrypt(self, decryption_materials): """Attempt to decrypt the encrypted data keys. :param decryption_materials: Contains verification key, list of encrypted data keys. - :type : aws_encryption_sdk.materials_managers.DecryptionMaterials - :returns decryption_materials: Contains verification key, list of encrypted data keys and decrypted data key. - :rtype : aws_encryption_sdk.materials_managers.DecryptionMaterials - :raises AttributeError: if decryption materials not available + :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials + :returns: Contains verification key, list of encrypted data keys and decrypted data key. + :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials + :raises NotImplementedError: if method is not implemented """ raise NotImplementedError("Keyring does not implement on_decrypt function") From 83ccdd3f286fe9b6aac726c99ee429c288bca7e4 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 20 Jun 2019 14:16:36 -0700 Subject: [PATCH 010/110] Raw keyring initial --- src/aws_encryption_sdk/keyring/raw_keyring.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 30d2bbd5a..2a853a462 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -12,6 +12,7 @@ # language governing permissions and limitations under the License. """Resources required for Raw Keyrings.""" import os + import attr import aws_encryption_sdk.internal.formatting.deserialize @@ -31,8 +32,7 @@ def on_encrypt(self, encryption_materials): # Encrypt data key wrapping_key = attr.ib(hash=True, validator=attr.validators.instance_of(WrappingKey)) encrypted_wrapped_key = wrapping_key.encrypt( - plaintext_data_key=plaintext_data_key, - encryption_context=encryption_materials.encryption_context + plaintext_data_key=plaintext_data_key, encryption_context=encryption_materials.encryption_context ) encrypted_data_key = aws_encryption_sdk.internal.formatting.serialize.serialize_wrapped_key( # WHAAAAT @@ -49,7 +49,7 @@ def on_encrypt(self, encryption_materials): encryption_materials.data_encryption_key = RawDataKey( # WHAAAAT key_provider=self.key_provider, - data_key=plaintext_data_key + data_key=plaintext_data_key, ) encryption_materials.encrypted_data_keys.add(encrypted_data_key) @@ -58,7 +58,6 @@ def on_encrypt(self, encryption_materials): def on_decrypt(self, decryption_materials): # Decrypt data key - # Update keyring trace return decryption_materials From aed1ed7e3d802fdba19482ecd1a214bed3ceb817 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 20 Jun 2019 14:19:54 -0700 Subject: [PATCH 011/110] Raw keyring encrypt commit --- requirements.txt | 1 + src/aws_encryption_sdk/keyring/raw_keyring.py | 28 +++++++++++++------ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/requirements.txt b/requirements.txt index f04114485..7540d66bf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +six boto3>=1.4.4 cryptography>=1.8.1 attrs>=17.4.0 diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 2a853a462..a2ab060bb 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -18,27 +18,38 @@ import aws_encryption_sdk.internal.formatting.deserialize import aws_encryption_sdk.internal.formatting.serialize from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey +from aws_encryption_sdk.identifiers import WrappingAlgorithm from aws_encryption_sdk.keyring.base import Keyring -from aws_encryption_sdk.structures import DataKey, RawDataKey +from aws_encryption_sdk.structures import DataKey, RawDataKey, MasterKeyInfo +@attr.s class RawAESKeyring(Keyring): """Public class for Raw AES Keyring.""" + provider_id = attr.ib(validator=attr.validators.instance_of(str)) + key_id = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) + wrapping_key = attr.ib(hash=True, validator=attr.validators.instance_of(WrappingKey)) + wrapping_algorithm = attr.ib(validator=attr.validators.instance_of(WrappingAlgorithm)) + + key_provider = MasterKeyInfo( + provider_id=provider_id, + key_info=key_id + ) + def on_encrypt(self, encryption_materials): # Generate data key plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) # Encrypt data key - wrapping_key = attr.ib(hash=True, validator=attr.validators.instance_of(WrappingKey)) - encrypted_wrapped_key = wrapping_key.encrypt( - plaintext_data_key=plaintext_data_key, encryption_context=encryption_materials.encryption_context + encrypted_wrapped_key = self.wrapping_key.encrypt( + plaintext_data_key=plaintext_data_key, + encryption_context=encryption_materials.encryption_context ) + encrypted_data_key = aws_encryption_sdk.internal.formatting.serialize.serialize_wrapped_key( - # WHAAAAT key_provider=self.key_provider, - wrapping_algorithm=wrapping_key.wrapping_algorithm, - # WHAAAAT + wrapping_algorithm=self.wrapping_algorithm, wrapping_key_id=self.key_id, encrypted_wrapped_key=encrypted_wrapped_key, ) @@ -47,7 +58,6 @@ def on_encrypt(self, encryption_materials): # Update encryption materials encryption_materials.data_encryption_key = RawDataKey( - # WHAAAAT key_provider=self.key_provider, data_key=plaintext_data_key, ) @@ -71,3 +81,5 @@ def on_encrypt(self, encryption_materials): def on_decrypt(self, decryption_materials): return decryption_materials + + From dc9352c948248f07962e89492097dd5e8ee4b5e6 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 20 Jun 2019 16:17:06 -0700 Subject: [PATCH 012/110] Encrypt functions for Raw RSA and AES --- src/aws_encryption_sdk/keyring/raw_keyring.py | 53 +++++++++++++------ 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index a2ab060bb..9bc5ad03e 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -17,25 +17,22 @@ import aws_encryption_sdk.internal.formatting.deserialize import aws_encryption_sdk.internal.formatting.serialize -from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey from aws_encryption_sdk.identifiers import WrappingAlgorithm +from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey from aws_encryption_sdk.keyring.base import Keyring -from aws_encryption_sdk.structures import DataKey, RawDataKey, MasterKeyInfo +from aws_encryption_sdk.structures import DataKey, MasterKeyInfo, RawDataKey @attr.s class RawAESKeyring(Keyring): """Public class for Raw AES Keyring.""" - provider_id = attr.ib(validator=attr.validators.instance_of(str)) - key_id = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) + key_namespace = attr.ib(validator=attr.validators.instance_of(str)) + key_name = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) wrapping_key = attr.ib(hash=True, validator=attr.validators.instance_of(WrappingKey)) wrapping_algorithm = attr.ib(validator=attr.validators.instance_of(WrappingAlgorithm)) - key_provider = MasterKeyInfo( - provider_id=provider_id, - key_info=key_id - ) + key_provider = MasterKeyInfo(provider_id=key_namespace, key_info=key_name) def on_encrypt(self, encryption_materials): # Generate data key @@ -43,14 +40,13 @@ def on_encrypt(self, encryption_materials): # Encrypt data key encrypted_wrapped_key = self.wrapping_key.encrypt( - plaintext_data_key=plaintext_data_key, - encryption_context=encryption_materials.encryption_context + plaintext_data_key=plaintext_data_key, encryption_context=encryption_materials.encryption_context ) encrypted_data_key = aws_encryption_sdk.internal.formatting.serialize.serialize_wrapped_key( key_provider=self.key_provider, wrapping_algorithm=self.wrapping_algorithm, - wrapping_key_id=self.key_id, + wrapping_key_id=self.key_name, encrypted_wrapped_key=encrypted_wrapped_key, ) @@ -58,8 +54,7 @@ def on_encrypt(self, encryption_materials): # Update encryption materials encryption_materials.data_encryption_key = RawDataKey( - key_provider=self.key_provider, - data_key=plaintext_data_key, + key_provider=self.key_provider, data_key=plaintext_data_key ) encryption_materials.encrypted_data_keys.add(encrypted_data_key) @@ -76,10 +71,38 @@ def on_decrypt(self, decryption_materials): class RawRSAKeyring(Keyring): """Public class for Raw RSA Keyring.""" + key_namespace = attr.ib(validator=attr.validators.instance_of(str)) + key_name = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) + wrapping_key = attr.ib(hash=True, validator=attr.validators.instance_of(WrappingKey)) + wrapping_algorithm = attr.ib(validator=attr.validators.instance_of(WrappingAlgorithm)) + + key_provider = MasterKeyInfo(provider_id=key_namespace, key_info=key_name) + def on_encrypt(self, encryption_materials): + # Generate data key + plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) + + # Encrypt data key + encrypted_wrapped_key = self.wrapping_key.encrypt( + plaintext_data_key=plaintext_data_key, encryption_context=encryption_materials.encryption_context + ) + + encrypted_data_key = aws_encryption_sdk.internal.formatting.serialize.serialize_wrapped_key( + key_provider=self.key_provider, + wrapping_algorithm=self.wrapping_algorithm, + wrapping_key_id=self.key_name, + encrypted_wrapped_key=encrypted_wrapped_key, + ) + + # Update keyring trace + + # Update encryption materials + encryption_materials.data_encryption_key = RawDataKey( + key_provider=self.key_provider, data_key=plaintext_data_key + ) + encryption_materials.encrypted_data_keys.add(encrypted_data_key) + return encryption_materials def on_decrypt(self, decryption_materials): return decryption_materials - - From b9c22b9b533c7ad9fbf28e6709f8342478e8b50e Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 20 Jun 2019 16:59:54 -0700 Subject: [PATCH 013/110] Raw RSA and AES initial --- src/aws_encryption_sdk/keyring/raw_keyring.py | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 9bc5ad03e..74e19c653 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -12,6 +12,7 @@ # language governing permissions and limitations under the License. """Resources required for Raw Keyrings.""" import os +import struct import attr @@ -19,6 +20,7 @@ import aws_encryption_sdk.internal.formatting.serialize from aws_encryption_sdk.identifiers import WrappingAlgorithm from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey +from aws_encryption_sdk.internal.str_ops import to_bytes from aws_encryption_sdk.keyring.base import Keyring from aws_encryption_sdk.structures import DataKey, MasterKeyInfo, RawDataKey @@ -34,7 +36,25 @@ class RawAESKeyring(Keyring): key_provider = MasterKeyInfo(provider_id=key_namespace, key_info=key_name) + key_info_prefix = struct.pack( + ">{}sII".format(len(key_name)), + to_bytes(key_name), + # Tag Length is stored in bits, not bytes + wrapping_algorithm.algorithm.tag_len * 8, + wrapping_algorithm.algorithm.iv_len, + ) + def on_encrypt(self, encryption_materials): + """Generate a data key if not present and encrypt it using any available wrapping key. + + :param encryption_materials: Contains signing key, encryption context and algorithm suite + required to encrypt data key + :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials + :returns: Contains signing key, unencrypted data key, encrypted data keys, + encryption context and algorithm suite required to encrypt data key + :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials + """ + # Generate data key plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) @@ -61,7 +81,35 @@ def on_encrypt(self, encryption_materials): return encryption_materials def on_decrypt(self, decryption_materials): + """Attempt to decrypt the encrypted data keys. + + :param decryption_materials: Contains verification key, list of encrypted data keys. + :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials + :returns: Contains verification key, list of encrypted data keys and decrypted data key. + :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials + """ + # Decrypt data key + expected_key_info_len = len(self.key_info_prefix) + self.wrapping_algorithm.algorithm.iv_len + if ( + decryption_materials.encrypted_data_key.key_provider.provider_id == self.key_provider.provider_id + and len(decryption_materials.encrypted_data_key.key_provider.key_info) == expected_key_info_len + and decryption_materials.encrypted_data_key.key_provider.key_info.startswith(self.key_info_prefix) + ): + encrypted_wrapped_key = aws_encryption_sdk.internal.formatting.deserialize.deserialize_wrapped_key( + wrapping_algorithm=self.wrapping_algorithm, + wrapping_key_id=self.key_name, + wrapped_encrypted_key=decryption_materials.encrypted_data_key, + ) + plaintext_data_key = self.wrapping_key.decrypt( + encrypted_wrapped_data_key=encrypted_wrapped_key, + encryption_context=decryption_materials.encryption_context, + ) + decryption_materials.data_key = DataKey( + key_provider=decryption_materials.encrypted_data_key.key_provider, + data_key=plaintext_data_key, + encrypted_data_key=decryption_materials.encrypted_data_key.encrypted_data_key, + ) # Update keyring trace @@ -79,6 +127,16 @@ class RawRSAKeyring(Keyring): key_provider = MasterKeyInfo(provider_id=key_namespace, key_info=key_name) def on_encrypt(self, encryption_materials): + """Generate a data key if not present and encrypt it using any available wrapping key. + + :param encryption_materials: Contains signing key, encryption context and algorithm suite + required to encrypt data key + :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials + :returns: Contains signing key, unencrypted data key, encrypted data keys, + encryption context and algorithm suite required to encrypt data key + :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials + """ + # Generate data key plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) @@ -105,4 +163,30 @@ def on_encrypt(self, encryption_materials): return encryption_materials def on_decrypt(self, decryption_materials): + """Attempt to decrypt the encrypted data keys. + + :param decryption_materials: Contains verification key, list of encrypted data keys. + :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials + :returns: Contains verification key, list of encrypted data keys and decrypted data key. + :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials + """ + + # Decrypt data key + if decryption_materials.encrypted_data_key.key_provider == self.key_provider: + encrypted_wrapped_key = aws_encryption_sdk.internal.formatting.deserialize.deserialize_wrapped_key( + wrapping_algorithm=self.wrapping_algorithm, + wrapping_key_id=self.key_name, + wrapped_encrypted_key=decryption_materials.encrypted_data_key, + ) + plaintext_data_key = self.wrapping_key.decrypt( + encrypted_wrapped_data_key=encrypted_wrapped_key, + encryption_context=decryption_materials.encryption_context, + ) + decryption_materials.data_key = DataKey( + key_provider=decryption_materials.encrypted_data_key.key_provider, + data_key=plaintext_data_key, + encrypted_data_key=decryption_materials.encrypted_data_key.encrypted_data_key, + ) + + # Update keyring trace return decryption_materials From 745c9ed34a068a702e568f759db3c4520beaacc4 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 27 Jun 2019 16:41:21 -0700 Subject: [PATCH 014/110] Changes in raw keyrings according to new keyring materials --- src/aws_encryption_sdk/keyring/raw_keyring.py | 240 ++++++++++-------- 1 file changed, 135 insertions(+), 105 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 74e19c653..71321e08d 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -13,6 +13,7 @@ """Resources required for Raw Keyrings.""" import os import struct +import six import attr @@ -23,27 +24,108 @@ from aws_encryption_sdk.internal.str_ops import to_bytes from aws_encryption_sdk.keyring.base import Keyring from aws_encryption_sdk.structures import DataKey, MasterKeyInfo, RawDataKey +from aws_encryption_sdk.exceptions import EncryptKeyError -@attr.s -class RawAESKeyring(Keyring): - """Public class for Raw AES Keyring.""" +def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping_algorithm, key_name): + # Check if data key already exists + if not encryption_materials.data_encryption_key: - key_namespace = attr.ib(validator=attr.validators.instance_of(str)) - key_name = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) - wrapping_key = attr.ib(hash=True, validator=attr.validators.instance_of(WrappingKey)) - wrapping_algorithm = attr.ib(validator=attr.validators.instance_of(WrappingAlgorithm)) + # Generate data key + plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) - key_provider = MasterKeyInfo(provider_id=key_namespace, key_info=key_name) + # Check if data key is generated + if not plaintext_data_key: + return EncryptKeyError("Unable to generate data encryption key.") - key_info_prefix = struct.pack( - ">{}sII".format(len(key_name)), - to_bytes(key_name), - # Tag Length is stored in bits, not bytes - wrapping_algorithm.algorithm.tag_len * 8, - wrapping_algorithm.algorithm.iv_len, + # plaintext_data_key to RawDataKey + data_encryption_key = RawDataKey( + key_provider=key_provider, data_key=plaintext_data_key + ) + + # Add generated data key to encryption_materials + encryption_materials.add_data_encryption_key(data_encryption_key, encryption_materials.keyring_trace) + + else: + plaintext_data_key = encryption_materials.data_encryption_key + + # Encrypt data key + encrypted_wrapped_key = wrapping_key.encrypt( + plaintext_data_key=plaintext_data_key, encryption_context=encryption_materials.encryption_context ) + # EncryptedData to EncryptedDataKey + encrypted_data_key = aws_encryption_sdk.internal.formatting.serialize.serialize_wrapped_key( + key_provider=key_provider, + wrapping_algorithm=wrapping_algorithm, + wrapping_key_id=key_name, + encrypted_wrapped_key=encrypted_wrapped_key + ) + + # Add encrypted data key to encryption_materials + encryption_materials.add_encrypted_data_key(encrypted_data_key, encryption_materials.keyring_trace) + + return encryption_materials + + +def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, key_name, encrypted_data_key): + # Check if plaintext data key exists + if decryption_materials.data_key: + return decryption_materials + + # Wrapped EncryptedDataKey to deserialized EncryptedData + encrypted_wrapped_key = aws_encryption_sdk.internal.formatting.deserialize.deserialize_wrapped_key( + wrapping_algorithm=wrapping_algorithm, + wrapping_key_id=key_name, + wrapped_encrypted_key=encrypted_data_key + ) + + # EncryptedData to raw key string + plaintext_data_key = wrapping_key.decrypt( + encrypted_wrapped_data_key=encrypted_wrapped_key, + encryption_context=decryption_materials.encryption_context + ) + + # Update decryption materials + data_encryption_key = DataKey( + key_provider=encrypted_data_key.key_provider, + data_key=plaintext_data_key, + encrypted_data_key=encrypted_data_key.encrypted_data_key + ) + decryption_materials.add_data_encryption_key(data_encryption_key, decryption_materials.keyring_trace) + + return decryption_materials + + +@attr.s +class RawAESKeyring(Keyring): + """Public class for Raw AES Keyring. + + :param str key_namespace: String defining the keyring ID + :param bytes key_name: Key ID + :param wrapping_key: Encryption key with which to wrap plaintext data key + :type wrapping_key: WrappingKey + :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key + :type wrapping_algorithm: WrappingAlgorithm + """ + + key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) + key_name = attr.ib(hash=True, validator=attr.validators.instance_of(six.binary_type)) + _wrapping_key = attr.ib(hash=True, repr=False, validator=attr.validators.instance_of(WrappingKey)) + _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) + + def __attrs_post_init__(self): + + _key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name) + + _key_info_prefix = struct.pack( + ">{}sII".format(len(self.key_name)), + to_bytes(self.key_name), + # Tag Length is stored in bits, not bytes + self._wrapping_algorithm.algorithm.tag_len * 8, + self._wrapping_algorithm.algorithm.iv_len + ) + def on_encrypt(self, encryption_materials): """Generate a data key if not present and encrypt it using any available wrapping key. @@ -55,76 +137,54 @@ def on_encrypt(self, encryption_materials): :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - # Generate data key - plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) - - # Encrypt data key - encrypted_wrapped_key = self.wrapping_key.encrypt( - plaintext_data_key=plaintext_data_key, encryption_context=encryption_materials.encryption_context - ) - - encrypted_data_key = aws_encryption_sdk.internal.formatting.serialize.serialize_wrapped_key( - key_provider=self.key_provider, - wrapping_algorithm=self.wrapping_algorithm, - wrapping_key_id=self.key_name, - encrypted_wrapped_key=encrypted_wrapped_key, - ) - - # Update keyring trace - - # Update encryption materials - encryption_materials.data_encryption_key = RawDataKey( - key_provider=self.key_provider, data_key=plaintext_data_key - ) - encryption_materials.encrypted_data_keys.add(encrypted_data_key) + encryption_materials = on_encrypt_helper(encryption_materials, self._key_provider, self._wrapping_key, + self._wrapping_algorithm, self.key_name) return encryption_materials - def on_decrypt(self, decryption_materials): + def on_decrypt(self, decryption_materials, encrypted_data_keys): """Attempt to decrypt the encrypted data keys. - :param decryption_materials: Contains verification key, list of encrypted data keys. + :param decryption_materials: Contains verification key, algorithm, encryption context and keyring trace. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials - :returns: Contains verification key, list of encrypted data keys and decrypted data key. + :param encrypted_data_keys: List of encrypted data keys. + :type: List of `aws_encryption_sdk.structures.EncryptedDataKey` + :returns: Contains verification key, algorithm, data_encryption_key, encryption context and keyring trac :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials """ # Decrypt data key - expected_key_info_len = len(self.key_info_prefix) + self.wrapping_algorithm.algorithm.iv_len + expected_key_info_len = len(self._key_info_prefix) + self._wrapping_algorithm.algorithm.iv_len if ( - decryption_materials.encrypted_data_key.key_provider.provider_id == self.key_provider.provider_id - and len(decryption_materials.encrypted_data_key.key_provider.key_info) == expected_key_info_len - and decryption_materials.encrypted_data_key.key_provider.key_info.startswith(self.key_info_prefix) + encrypted_data_keys.key_provider.provider_id == self._key_provider.provider_id + and len(encrypted_data_keys.key_provider.key_info) == expected_key_info_len + and encrypted_data_keys.key_provider.key_info.startswith(self._key_info_prefix) ): - encrypted_wrapped_key = aws_encryption_sdk.internal.formatting.deserialize.deserialize_wrapped_key( - wrapping_algorithm=self.wrapping_algorithm, - wrapping_key_id=self.key_name, - wrapped_encrypted_key=decryption_materials.encrypted_data_key, - ) - plaintext_data_key = self.wrapping_key.decrypt( - encrypted_wrapped_data_key=encrypted_wrapped_key, - encryption_context=decryption_materials.encryption_context, - ) - decryption_materials.data_key = DataKey( - key_provider=decryption_materials.encrypted_data_key.key_provider, - data_key=plaintext_data_key, - encrypted_data_key=decryption_materials.encrypted_data_key.encrypted_data_key, - ) - - # Update keyring trace + decryption_materials = on_decrypt_helper(decryption_materials, self._wrapping_key, self._wrapping_algorithm, + self.key_name, encrypted_data_keys) return decryption_materials class RawRSAKeyring(Keyring): - """Public class for Raw RSA Keyring.""" + """Public class for Raw RSA Keyring. + + :param str key_namespace: String defining the keyring ID + :param bytes key_name: Key ID + :param wrapping_key: Encryption key with which to wrap plaintext data key + :type wrapping_key: WrappingKey + :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key + :type wrapping_algorithm: WrappingAlgorithm + :param key_provider: Complete information about the key in the keyring + :type key_provider: MasterKeyInfo + """ key_namespace = attr.ib(validator=attr.validators.instance_of(str)) key_name = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) - wrapping_key = attr.ib(hash=True, validator=attr.validators.instance_of(WrappingKey)) - wrapping_algorithm = attr.ib(validator=attr.validators.instance_of(WrappingAlgorithm)) + _wrapping_key = attr.ib(hash=True, repr=False, validator=attr.validators.instance_of(WrappingKey)) + _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) - key_provider = MasterKeyInfo(provider_id=key_namespace, key_info=key_name) + _key_provider = MasterKeyInfo(provider_id=key_namespace, key_info=key_name) def on_encrypt(self, encryption_materials): """Generate a data key if not present and encrypt it using any available wrapping key. @@ -137,56 +197,26 @@ def on_encrypt(self, encryption_materials): :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - # Generate data key - plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) - - # Encrypt data key - encrypted_wrapped_key = self.wrapping_key.encrypt( - plaintext_data_key=plaintext_data_key, encryption_context=encryption_materials.encryption_context - ) - - encrypted_data_key = aws_encryption_sdk.internal.formatting.serialize.serialize_wrapped_key( - key_provider=self.key_provider, - wrapping_algorithm=self.wrapping_algorithm, - wrapping_key_id=self.key_name, - encrypted_wrapped_key=encrypted_wrapped_key, - ) - - # Update keyring trace - - # Update encryption materials - encryption_materials.data_encryption_key = RawDataKey( - key_provider=self.key_provider, data_key=plaintext_data_key - ) - encryption_materials.encrypted_data_keys.add(encrypted_data_key) + encryption_materials = on_encrypt_helper(encryption_materials, self._key_provider, self._wrapping_key, + self._wrapping_algorithm, self.key_name) return encryption_materials - def on_decrypt(self, decryption_materials): + def on_decrypt(self, decryption_materials, encrypted_data_keys): """Attempt to decrypt the encrypted data keys. - :param decryption_materials: Contains verification key, list of encrypted data keys. + :param decryption_materials: Contains verification key, algorithm, encryption context and keyring trace. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials - :returns: Contains verification key, list of encrypted data keys and decrypted data key. + :param encrypted_data_keys: List of encrypted data keys. + :type: List of `aws_encryption_sdk.structures.EncryptedDataKey` + :returns: Contains verification key, algorithm, data_encryption_key, encryption context and keyring trac :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials """ # Decrypt data key - if decryption_materials.encrypted_data_key.key_provider == self.key_provider: - encrypted_wrapped_key = aws_encryption_sdk.internal.formatting.deserialize.deserialize_wrapped_key( - wrapping_algorithm=self.wrapping_algorithm, - wrapping_key_id=self.key_name, - wrapped_encrypted_key=decryption_materials.encrypted_data_key, - ) - plaintext_data_key = self.wrapping_key.decrypt( - encrypted_wrapped_data_key=encrypted_wrapped_key, - encryption_context=decryption_materials.encryption_context, - ) - decryption_materials.data_key = DataKey( - key_provider=decryption_materials.encrypted_data_key.key_provider, - data_key=plaintext_data_key, - encrypted_data_key=decryption_materials.encrypted_data_key.encrypted_data_key, - ) - - # Update keyring trace + if encrypted_data_keys.key_provider == self._key_provider: + + decryption_materials = on_decrypt_helper(decryption_materials, self._wrapping_key, self._wrapping_algorithm, + self.key_name, encrypted_data_keys) + return decryption_materials From bb163bc0da10d776e5c3171cef22cb007e731c7e Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 27 Jun 2019 16:53:19 -0700 Subject: [PATCH 015/110] Updated with autoformat --- src/aws_encryption_sdk/keyring/raw_keyring.py | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 71321e08d..50b1661ca 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -13,18 +13,18 @@ """Resources required for Raw Keyrings.""" import os import struct -import six import attr +import six import aws_encryption_sdk.internal.formatting.deserialize import aws_encryption_sdk.internal.formatting.serialize +from aws_encryption_sdk.exceptions import EncryptKeyError from aws_encryption_sdk.identifiers import WrappingAlgorithm from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey from aws_encryption_sdk.internal.str_ops import to_bytes from aws_encryption_sdk.keyring.base import Keyring from aws_encryption_sdk.structures import DataKey, MasterKeyInfo, RawDataKey -from aws_encryption_sdk.exceptions import EncryptKeyError def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping_algorithm, key_name): @@ -39,9 +39,7 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping return EncryptKeyError("Unable to generate data encryption key.") # plaintext_data_key to RawDataKey - data_encryption_key = RawDataKey( - key_provider=key_provider, data_key=plaintext_data_key - ) + data_encryption_key = RawDataKey(key_provider=key_provider, data_key=plaintext_data_key) # Add generated data key to encryption_materials encryption_materials.add_data_encryption_key(data_encryption_key, encryption_materials.keyring_trace) @@ -59,7 +57,7 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping key_provider=key_provider, wrapping_algorithm=wrapping_algorithm, wrapping_key_id=key_name, - encrypted_wrapped_key=encrypted_wrapped_key + encrypted_wrapped_key=encrypted_wrapped_key, ) # Add encrypted data key to encryption_materials @@ -75,22 +73,19 @@ def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, ke # Wrapped EncryptedDataKey to deserialized EncryptedData encrypted_wrapped_key = aws_encryption_sdk.internal.formatting.deserialize.deserialize_wrapped_key( - wrapping_algorithm=wrapping_algorithm, - wrapping_key_id=key_name, - wrapped_encrypted_key=encrypted_data_key + wrapping_algorithm=wrapping_algorithm, wrapping_key_id=key_name, wrapped_encrypted_key=encrypted_data_key ) # EncryptedData to raw key string plaintext_data_key = wrapping_key.decrypt( - encrypted_wrapped_data_key=encrypted_wrapped_key, - encryption_context=decryption_materials.encryption_context + encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=decryption_materials.encryption_context ) # Update decryption materials data_encryption_key = DataKey( key_provider=encrypted_data_key.key_provider, data_key=plaintext_data_key, - encrypted_data_key=encrypted_data_key.encrypted_data_key + encrypted_data_key=encrypted_data_key.encrypted_data_key, ) decryption_materials.add_data_encryption_key(data_encryption_key, decryption_materials.keyring_trace) @@ -123,7 +118,7 @@ def __attrs_post_init__(self): to_bytes(self.key_name), # Tag Length is stored in bits, not bytes self._wrapping_algorithm.algorithm.tag_len * 8, - self._wrapping_algorithm.algorithm.iv_len + self._wrapping_algorithm.algorithm.iv_len, ) def on_encrypt(self, encryption_materials): @@ -137,8 +132,9 @@ def on_encrypt(self, encryption_materials): :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - encryption_materials = on_encrypt_helper(encryption_materials, self._key_provider, self._wrapping_key, - self._wrapping_algorithm, self.key_name) + encryption_materials = on_encrypt_helper( + encryption_materials, self._key_provider, self._wrapping_key, self._wrapping_algorithm, self.key_name + ) return encryption_materials @@ -160,8 +156,9 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): and len(encrypted_data_keys.key_provider.key_info) == expected_key_info_len and encrypted_data_keys.key_provider.key_info.startswith(self._key_info_prefix) ): - decryption_materials = on_decrypt_helper(decryption_materials, self._wrapping_key, self._wrapping_algorithm, - self.key_name, encrypted_data_keys) + decryption_materials = on_decrypt_helper( + decryption_materials, self._wrapping_key, self._wrapping_algorithm, self.key_name, encrypted_data_keys + ) return decryption_materials @@ -197,8 +194,9 @@ def on_encrypt(self, encryption_materials): :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - encryption_materials = on_encrypt_helper(encryption_materials, self._key_provider, self._wrapping_key, - self._wrapping_algorithm, self.key_name) + encryption_materials = on_encrypt_helper( + encryption_materials, self._key_provider, self._wrapping_key, self._wrapping_algorithm, self.key_name + ) return encryption_materials @@ -216,7 +214,8 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): # Decrypt data key if encrypted_data_keys.key_provider == self._key_provider: - decryption_materials = on_decrypt_helper(decryption_materials, self._wrapping_key, self._wrapping_algorithm, - self.key_name, encrypted_data_keys) + decryption_materials = on_decrypt_helper( + decryption_materials, self._wrapping_key, self._wrapping_algorithm, self.key_name, encrypted_data_keys + ) return decryption_materials From 27fe8d93d92c8526957a902490139777f0f143bd Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Fri, 28 Jun 2019 09:44:27 -0700 Subject: [PATCH 016/110] Modified base --- src/aws_encryption_sdk/keyring/base.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index 3c4689d70..3192a5688 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -14,7 +14,10 @@ class Keyring(object): - """Parent interface for Keyring classes.""" + """Parent interface for Keyring classes. + + .. versionadded:: 1.5.0 + """ def on_encrypt(self, encryption_materials): """Generate a data key if not present and encrypt it using any available wrapping key. @@ -22,19 +25,22 @@ def on_encrypt(self, encryption_materials): :param encryption_materials: Contains signing key, encryption context and algorithm suite required to encrypt data key :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials - :returns: Contains signing key, unencrypted data key, encrypted data keys, + :returns: Encryption materials containing signing key, unencrypted data key, encrypted data keys, encryption context and algorithm suite required to encrypt data key :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials :raises NotImplementedError: if method is not implemented """ raise NotImplementedError("Keyring does not implement on_encrypt function") - def on_decrypt(self, decryption_materials): + def on_decrypt(self, decryption_materials, encrypted_data_keys): """Attempt to decrypt the encrypted data keys. - :param decryption_materials: Contains verification key, list of encrypted data keys. + :param decryption_materials: May contain verification key, algorithm, encryption context and keyring trace. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials - :returns: Contains verification key, list of encrypted data keys and decrypted data key. + :param encrypted_data_keys: List of encrypted data keys. + :type: Iterable of `aws_encryption_sdk.structures.EncryptedDataKey` + :returns: Decryption materials containing verification key, algorithm, data_encryption_key, + encryption context and keyring trace. :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials :raises NotImplementedError: if method is not implemented """ From e8286ac0ffaf169b7abcdb74996eb90b9059f887 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Fri, 28 Jun 2019 16:22:38 -0700 Subject: [PATCH 017/110] Corrected tox and flake errors --- src/aws_encryption_sdk/keyring/raw_keyring.py | 57 ++++++++++++++----- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 50b1661ca..25b805727 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -11,6 +11,7 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Resources required for Raw Keyrings.""" + import os import struct @@ -28,6 +29,21 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping_algorithm, key_name): + """Helper function for the on_encrypt function of keyring. + + :param encryption_materials: Encryption materials for the keyring to modify. + :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials + :param key_provider: Information abput the key in the keyring. + :type key_provider: MasterKeyInfo + :param wrapping_key: Encryption key with which to wrap plaintext data key. + :type wrapping_key: WrappingKey + :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key. + :type wrapping_algorithm: WrappingAlgorithm + :param bytes key_name: Key ID. + :return: Optionally modified encryption materials. + :rtype encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials + """ + # Check if data key already exists if not encryption_materials.data_encryption_key: @@ -67,6 +83,21 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, key_name, encrypted_data_key): + """Helper function for the on_decrypt function of keyring. + + :param decryption_materials: Decryption materials for the keyring to modify. + :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials + :param wrapping_key: Encryption key with which to wrap plaintext data key. + :type wrapping_key: WrappingKey + :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key. + :type wrapping_algorithm: WrappingAlgorithm + :param bytes key_name: Key ID. + :param encrypted_data_key: Data key encrypted with a wrapping key. + :type encrypted_data_key: aws_encryption_sdk.structures.EncryptedDataKey + :return: Optionally modified decryption materials. + :rtype decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials + """ + # Check if plaintext data key exists if decryption_materials.data_key: return decryption_materials @@ -96,11 +127,11 @@ def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, ke class RawAESKeyring(Keyring): """Public class for Raw AES Keyring. - :param str key_namespace: String defining the keyring ID + :param str key_namespace: String defining the keyring. :param bytes key_name: Key ID - :param wrapping_key: Encryption key with which to wrap plaintext data key + :param wrapping_key: Encryption key with which to wrap plaintext data key. :type wrapping_key: WrappingKey - :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key + :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key. :type wrapping_algorithm: WrappingAlgorithm """ @@ -124,11 +155,9 @@ def __attrs_post_init__(self): def on_encrypt(self, encryption_materials): """Generate a data key if not present and encrypt it using any available wrapping key. - :param encryption_materials: Contains signing key, encryption context and algorithm suite - required to encrypt data key + :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials - :returns: Contains signing key, unencrypted data key, encrypted data keys, - encryption context and algorithm suite required to encrypt data key + :returns: Optionally modified encryption materials. :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ @@ -141,11 +170,11 @@ def on_encrypt(self, encryption_materials): def on_decrypt(self, decryption_materials, encrypted_data_keys): """Attempt to decrypt the encrypted data keys. - :param decryption_materials: Contains verification key, algorithm, encryption context and keyring trace. + :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials :param encrypted_data_keys: List of encrypted data keys. :type: List of `aws_encryption_sdk.structures.EncryptedDataKey` - :returns: Contains verification key, algorithm, data_encryption_key, encryption context and keyring trac + :returns: Optionally modified decryption materials. :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials """ @@ -186,11 +215,9 @@ class RawRSAKeyring(Keyring): def on_encrypt(self, encryption_materials): """Generate a data key if not present and encrypt it using any available wrapping key. - :param encryption_materials: Contains signing key, encryption context and algorithm suite - required to encrypt data key + :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials - :returns: Contains signing key, unencrypted data key, encrypted data keys, - encryption context and algorithm suite required to encrypt data key + :returns: Optionally modified encryption materials. :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ @@ -203,11 +230,11 @@ def on_encrypt(self, encryption_materials): def on_decrypt(self, decryption_materials, encrypted_data_keys): """Attempt to decrypt the encrypted data keys. - :param decryption_materials: Contains verification key, algorithm, encryption context and keyring trace. + :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials :param encrypted_data_keys: List of encrypted data keys. :type: List of `aws_encryption_sdk.structures.EncryptedDataKey` - :returns: Contains verification key, algorithm, data_encryption_key, encryption context and keyring trac + :returns: Optionally modified decryption materials. :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials """ From eef26e7a812c94a220fd39f34280e0553581af23 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Mon, 1 Jul 2019 09:25:38 -0700 Subject: [PATCH 018/110] Docstring error correction --- src/aws_encryption_sdk/keyring/raw_keyring.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 25b805727..ebe61f3a9 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -30,7 +30,6 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping_algorithm, key_name): """Helper function for the on_encrypt function of keyring. - :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials :param key_provider: Information abput the key in the keyring. @@ -84,7 +83,6 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, key_name, encrypted_data_key): """Helper function for the on_decrypt function of keyring. - :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials :param wrapping_key: Encryption key with which to wrap plaintext data key. @@ -126,7 +124,6 @@ def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, ke @attr.s class RawAESKeyring(Keyring): """Public class for Raw AES Keyring. - :param str key_namespace: String defining the keyring. :param bytes key_name: Key ID :param wrapping_key: Encryption key with which to wrap plaintext data key. @@ -154,7 +151,6 @@ def __attrs_post_init__(self): def on_encrypt(self, encryption_materials): """Generate a data key if not present and encrypt it using any available wrapping key. - :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials :returns: Optionally modified encryption materials. @@ -169,7 +165,6 @@ def on_encrypt(self, encryption_materials): def on_decrypt(self, decryption_materials, encrypted_data_keys): """Attempt to decrypt the encrypted data keys. - :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials :param encrypted_data_keys: List of encrypted data keys. @@ -194,7 +189,6 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): class RawRSAKeyring(Keyring): """Public class for Raw RSA Keyring. - :param str key_namespace: String defining the keyring ID :param bytes key_name: Key ID :param wrapping_key: Encryption key with which to wrap plaintext data key @@ -214,7 +208,6 @@ class RawRSAKeyring(Keyring): def on_encrypt(self, encryption_materials): """Generate a data key if not present and encrypt it using any available wrapping key. - :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials :returns: Optionally modified encryption materials. @@ -229,7 +222,6 @@ def on_encrypt(self, encryption_materials): def on_decrypt(self, decryption_materials, encrypted_data_keys): """Attempt to decrypt the encrypted data keys. - :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials :param encrypted_data_keys: List of encrypted data keys. From 900a06444d794ac5791dd94da0c54418c8bb63c2 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Mon, 1 Jul 2019 10:27:41 -0700 Subject: [PATCH 019/110] Added docstrings and corrected errors --- src/aws_encryption_sdk/keyring/raw_keyring.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index ebe61f3a9..11b442777 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -30,6 +30,7 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping_algorithm, key_name): """Helper function for the on_encrypt function of keyring. + :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials :param key_provider: Information abput the key in the keyring. @@ -42,7 +43,6 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping :return: Optionally modified encryption materials. :rtype encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - # Check if data key already exists if not encryption_materials.data_encryption_key: @@ -83,6 +83,7 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, key_name, encrypted_data_key): """Helper function for the on_decrypt function of keyring. + :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials :param wrapping_key: Encryption key with which to wrap plaintext data key. @@ -95,7 +96,6 @@ def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, ke :return: Optionally modified decryption materials. :rtype decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials """ - # Check if plaintext data key exists if decryption_materials.data_key: return decryption_materials @@ -124,6 +124,7 @@ def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, ke @attr.s class RawAESKeyring(Keyring): """Public class for Raw AES Keyring. + :param str key_namespace: String defining the keyring. :param bytes key_name: Key ID :param wrapping_key: Encryption key with which to wrap plaintext data key. @@ -131,17 +132,16 @@ class RawAESKeyring(Keyring): :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key. :type wrapping_algorithm: WrappingAlgorithm """ - key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) key_name = attr.ib(hash=True, validator=attr.validators.instance_of(six.binary_type)) _wrapping_key = attr.ib(hash=True, repr=False, validator=attr.validators.instance_of(WrappingKey)) _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) def __attrs_post_init__(self): + """Prepares initial values not handled by attrs.""" + self._key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name) - _key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name) - - _key_info_prefix = struct.pack( + self._key_info_prefix = struct.pack( ">{}sII".format(len(self.key_name)), to_bytes(self.key_name), # Tag Length is stored in bits, not bytes @@ -151,12 +151,12 @@ def __attrs_post_init__(self): def on_encrypt(self, encryption_materials): """Generate a data key if not present and encrypt it using any available wrapping key. + :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials :returns: Optionally modified encryption materials. :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - encryption_materials = on_encrypt_helper( encryption_materials, self._key_provider, self._wrapping_key, self._wrapping_algorithm, self.key_name ) @@ -165,6 +165,7 @@ def on_encrypt(self, encryption_materials): def on_decrypt(self, decryption_materials, encrypted_data_keys): """Attempt to decrypt the encrypted data keys. + :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials :param encrypted_data_keys: List of encrypted data keys. @@ -172,7 +173,6 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): :returns: Optionally modified decryption materials. :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials """ - # Decrypt data key expected_key_info_len = len(self._key_info_prefix) + self._wrapping_algorithm.algorithm.iv_len if ( @@ -189,6 +189,7 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): class RawRSAKeyring(Keyring): """Public class for Raw RSA Keyring. + :param str key_namespace: String defining the keyring ID :param bytes key_name: Key ID :param wrapping_key: Encryption key with which to wrap plaintext data key @@ -198,7 +199,6 @@ class RawRSAKeyring(Keyring): :param key_provider: Complete information about the key in the keyring :type key_provider: MasterKeyInfo """ - key_namespace = attr.ib(validator=attr.validators.instance_of(str)) key_name = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) _wrapping_key = attr.ib(hash=True, repr=False, validator=attr.validators.instance_of(WrappingKey)) @@ -208,12 +208,12 @@ class RawRSAKeyring(Keyring): def on_encrypt(self, encryption_materials): """Generate a data key if not present and encrypt it using any available wrapping key. + :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials :returns: Optionally modified encryption materials. :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - encryption_materials = on_encrypt_helper( encryption_materials, self._key_provider, self._wrapping_key, self._wrapping_algorithm, self.key_name ) @@ -222,6 +222,7 @@ def on_encrypt(self, encryption_materials): def on_decrypt(self, decryption_materials, encrypted_data_keys): """Attempt to decrypt the encrypted data keys. + :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials :param encrypted_data_keys: List of encrypted data keys. @@ -229,7 +230,6 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): :returns: Optionally modified decryption materials. :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials """ - # Decrypt data key if encrypted_data_keys.key_provider == self._key_provider: From c500970d34b3a0bfde64c6985f84e6634e11cf84 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Mon, 1 Jul 2019 11:09:24 -0700 Subject: [PATCH 020/110] Some more changes in docstrings --- src/aws_encryption_sdk/keyring/raw_keyring.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 11b442777..a0d9de69a 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -132,6 +132,7 @@ class RawAESKeyring(Keyring): :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key. :type wrapping_algorithm: WrappingAlgorithm """ + key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) key_name = attr.ib(hash=True, validator=attr.validators.instance_of(six.binary_type)) _wrapping_key = attr.ib(hash=True, repr=False, validator=attr.validators.instance_of(WrappingKey)) @@ -199,6 +200,7 @@ class RawRSAKeyring(Keyring): :param key_provider: Complete information about the key in the keyring :type key_provider: MasterKeyInfo """ + key_namespace = attr.ib(validator=attr.validators.instance_of(str)) key_name = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) _wrapping_key = attr.ib(hash=True, repr=False, validator=attr.validators.instance_of(WrappingKey)) From 8a00e15712fe45d3639d9d16c1768a9ea15e9819 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Mon, 1 Jul 2019 11:55:51 -0700 Subject: [PATCH 021/110] Updating base API --- src/aws_encryption_sdk/keyring/base.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index 3192a5688..770b53c0b 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -11,6 +11,14 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Base class interface for Keyrings.""" +from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials +from aws_encryption_sdk.structures import EncryptedDataKey + +try: # Python 3.5.0 and 3.5.1 have incompatible typing modules + from typing import Iterable # noqa pylint: disable=unused-import +except ImportError: # pragma: no cover + # We only actually need these imports when running the mypy checks + pass class Keyring(object): @@ -20,27 +28,26 @@ class Keyring(object): """ def on_encrypt(self, encryption_materials): + # type: (EncryptionMaterials) -> EncryptionMaterials """Generate a data key if not present and encrypt it using any available wrapping key. - :param encryption_materials: Contains signing key, encryption context and algorithm suite - required to encrypt data key + :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials - :returns: Encryption materials containing signing key, unencrypted data key, encrypted data keys, - encryption context and algorithm suite required to encrypt data key + :returns: Optionally modified encryption materials. :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials :raises NotImplementedError: if method is not implemented """ raise NotImplementedError("Keyring does not implement on_encrypt function") def on_decrypt(self, decryption_materials, encrypted_data_keys): + # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials """Attempt to decrypt the encrypted data keys. - :param decryption_materials: May contain verification key, algorithm, encryption context and keyring trace. + :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials :param encrypted_data_keys: List of encrypted data keys. - :type: Iterable of `aws_encryption_sdk.structures.EncryptedDataKey` - :returns: Decryption materials containing verification key, algorithm, data_encryption_key, - encryption context and keyring trace. + :type: Iterable of :class:`aws_encryption_sdk.structures.EncryptedDataKey` + :returns: Optionally modified decryption materials. :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials :raises NotImplementedError: if method is not implemented """ From 250f55487967293063d6cf63387a94842100f4b0 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 2 Jul 2019 15:22:54 -0700 Subject: [PATCH 022/110] Made all suggested changes --- src/aws_encryption_sdk/keyring/raw_keyring.py | 173 +++++++++++++----- 1 file changed, 124 insertions(+), 49 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index a0d9de69a..344920196 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -13,27 +13,58 @@ """Resources required for Raw Keyrings.""" import os -import struct +import logging import attr import six -import aws_encryption_sdk.internal.formatting.deserialize -import aws_encryption_sdk.internal.formatting.serialize +from aws_encryption_sdk.internal.formatting.deserialize import deserialize_wrapped_key +from aws_encryption_sdk.internal.formatting.serialize import serialize_wrapped_key, serialize_raw_master_key_prefix from aws_encryption_sdk.exceptions import EncryptKeyError -from aws_encryption_sdk.identifiers import WrappingAlgorithm +from aws_encryption_sdk.identifiers import WrappingAlgorithm, EncryptionKeyType from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey -from aws_encryption_sdk.internal.str_ops import to_bytes from aws_encryption_sdk.keyring.base import Keyring -from aws_encryption_sdk.structures import DataKey, MasterKeyInfo, RawDataKey +from aws_encryption_sdk.structures import MasterKeyInfo, RawDataKey, KeyringTrace +from aws_encryption_sdk.key_providers.raw import RawMasterKey +try: # Python 3.5.0 and 3.5.1 have incompatible typing modules + from typing import Iterable # noqa pylint: disable=unused-import +except ImportError: # pragma: no cover + # We only actually need these imports when running the mypy checks + pass -def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping_algorithm, key_name): + +def get_key_info_prefix(key_namespace, key_name, wrapping_key): + # type: (str, bytes, WrappingKey) -> six.binary_type + """Helper function to get key info prefix + + :param str key_namespace: String defining the keyring. + :param bytes key_name: Key ID + :param wrapping_key: Encryption key with which to wrap plaintext data key. + :type wrapping_key: WrappingKey + :return: Serialized key_info prefix + :rtype: bytes + """ + key_info_prefix = serialize_raw_master_key_prefix(RawMasterKey(provider_id=key_namespace, + key_id=key_name, + wrapping_key=wrapping_key + ) + ) + return key_info_prefix + + +def on_encrypt_helper(encryption_materials, # type: EncryptionMaterials + key_provider, # type: MasterKeyInfo + wrapping_key, # type: WrappingKey + wrapping_algorithm, # type: WrappingAlgorithm + key_name # type: bytes + ): + # type: (...) -> EncryptionMaterials """Helper function for the on_encrypt function of keyring. :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials - :param key_provider: Information abput the key in the keyring. + :param key_provider: Information about the key in the keyring. :type key_provider: MasterKeyInfo :param wrapping_key: Encryption key with which to wrap plaintext data key. :type wrapping_key: WrappingKey @@ -43,6 +74,12 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping :return: Optionally modified encryption materials. :rtype encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials """ + # Create a keyring trace + keyring_trace = KeyringTrace( + wrapping_key=key_provider, + flags=set() + ) + # Check if data key already exists if not encryption_materials.data_encryption_key: @@ -57,7 +94,7 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping data_encryption_key = RawDataKey(key_provider=key_provider, data_key=plaintext_data_key) # Add generated data key to encryption_materials - encryption_materials.add_data_encryption_key(data_encryption_key, encryption_materials.keyring_trace) + encryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) else: plaintext_data_key = encryption_materials.data_encryption_key @@ -68,7 +105,7 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping ) # EncryptedData to EncryptedDataKey - encrypted_data_key = aws_encryption_sdk.internal.formatting.serialize.serialize_wrapped_key( + encrypted_data_key = serialize_wrapped_key( key_provider=key_provider, wrapping_algorithm=wrapping_algorithm, wrapping_key_id=key_name, @@ -76,16 +113,25 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping ) # Add encrypted data key to encryption_materials - encryption_materials.add_encrypted_data_key(encrypted_data_key, encryption_materials.keyring_trace) + encryption_materials.add_encrypted_data_key(encrypted_data_key, keyring_trace) return encryption_materials -def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, key_name, encrypted_data_key): +def on_decrypt_helper(decryption_materials, # type: DecryptionMaterials + key_provider, # type: MasterKeyInfo + wrapping_key, # type: WrappingKey + wrapping_algorithm, # type: WrappingAlgorithm + key_name, # type: bytes + encrypted_data_key # type: EncryptedDataKey + ): + # type: (...) -> DecryptionMaterials """Helper function for the on_decrypt function of keyring. :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials + :param key_provider: Information about the key in the keyring. + :type key_provider: MasterKeyInfo :param wrapping_key: Encryption key with which to wrap plaintext data key. :type wrapping_key: WrappingKey :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key. @@ -96,27 +142,37 @@ def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, ke :return: Optionally modified decryption materials. :rtype decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials """ + # Create a keyring trace + keyring_trace = KeyringTrace( + wrapping_key=key_provider, + flags=set() + ) + # Check if plaintext data key exists if decryption_materials.data_key: return decryption_materials # Wrapped EncryptedDataKey to deserialized EncryptedData - encrypted_wrapped_key = aws_encryption_sdk.internal.formatting.deserialize.deserialize_wrapped_key( + encrypted_wrapped_key = deserialize_wrapped_key( wrapping_algorithm=wrapping_algorithm, wrapping_key_id=key_name, wrapped_encrypted_key=encrypted_data_key ) # EncryptedData to raw key string - plaintext_data_key = wrapping_key.decrypt( - encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=decryption_materials.encryption_context - ) + try: + plaintext_data_key = wrapping_key.decrypt( + encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=decryption_materials.encryption_context + ) + except Exception as error: + logging.ERROR(error.__class__.__name__, ':', str(error)) + return decryption_materials # Update decryption materials - data_encryption_key = DataKey( - key_provider=encrypted_data_key.key_provider, - data_key=plaintext_data_key, - encrypted_data_key=encrypted_data_key.encrypted_data_key, + data_encryption_key = RawDataKey( + key_provider=MasterKeyInfo(provider_id=key_provider.provider_id, + key_info=key_name), + data_key=plaintext_data_key ) - decryption_materials.add_data_encryption_key(data_encryption_key, decryption_materials.keyring_trace) + decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) return decryption_materials @@ -134,23 +190,26 @@ class RawAESKeyring(Keyring): """ key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) - key_name = attr.ib(hash=True, validator=attr.validators.instance_of(six.binary_type)) - _wrapping_key = attr.ib(hash=True, repr=False, validator=attr.validators.instance_of(WrappingKey)) + key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) + _wrapping_key = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingKey)) _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) def __attrs_post_init__(self): + # type: () -> None """Prepares initial values not handled by attrs.""" self._key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name) - self._key_info_prefix = struct.pack( - ">{}sII".format(len(self.key_name)), - to_bytes(self.key_name), - # Tag Length is stored in bits, not bytes - self._wrapping_algorithm.algorithm.tag_len * 8, - self._wrapping_algorithm.algorithm.iv_len, - ) + self._key_info_prefix = get_key_info_prefix(key_namespace=self.key_namespace, + key_name=self.key_name, + wrapping_key=WrappingKey( + wrapping_algorithm=self._wrapping_algorithm, + wrapping_key=self._wrapping_key, + wrapping_key_type=EncryptionKeyType.SYMMETRIC + ) + ) def on_encrypt(self, encryption_materials): + # type: (EncryptionMaterials) -> EncryptionMaterials """Generate a data key if not present and encrypt it using any available wrapping key. :param encryption_materials: Encryption materials for the keyring to modify. @@ -159,12 +218,15 @@ def on_encrypt(self, encryption_materials): :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ encryption_materials = on_encrypt_helper( - encryption_materials, self._key_provider, self._wrapping_key, self._wrapping_algorithm, self.key_name + encryption_materials=encryption_materials, key_provider=self._key_provider, + wrapping_key=self._wrapping_key, wrapping_algorithm=self._wrapping_algorithm, + key_name=self.key_name ) return encryption_materials def on_decrypt(self, decryption_materials, encrypted_data_keys): + # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials """Attempt to decrypt the encrypted data keys. :param decryption_materials: Decryption materials for the keyring to modify. @@ -176,14 +238,18 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): """ # Decrypt data key expected_key_info_len = len(self._key_info_prefix) + self._wrapping_algorithm.algorithm.iv_len - if ( - encrypted_data_keys.key_provider.provider_id == self._key_provider.provider_id - and len(encrypted_data_keys.key_provider.key_info) == expected_key_info_len - and encrypted_data_keys.key_provider.key_info.startswith(self._key_info_prefix) - ): - decryption_materials = on_decrypt_helper( - decryption_materials, self._wrapping_key, self._wrapping_algorithm, self.key_name, encrypted_data_keys - ) + for key in encrypted_data_keys: + if (key.key_provider.provider_id == self._key_provider.provider_id + and len(key.key_provider.key_info) == expected_key_info_len + and key.key_provider.key_info.startswith(self._key_info_prefix) + ): + decryption_materials = on_decrypt_helper( + decryption_materials=decryption_materials, key_provider=self._key_provider, + wrapping_key=self._wrapping_key, wrapping_algorithm=self._wrapping_algorithm, + key_name=self.key_name, encrypted_data_key=key + ) + if decryption_materials.data_key: + return decryption_materials return decryption_materials @@ -201,14 +267,18 @@ class RawRSAKeyring(Keyring): :type key_provider: MasterKeyInfo """ - key_namespace = attr.ib(validator=attr.validators.instance_of(str)) - key_name = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) - _wrapping_key = attr.ib(hash=True, repr=False, validator=attr.validators.instance_of(WrappingKey)) + key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) + key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) + _wrapping_key = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingKey)) _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) - _key_provider = MasterKeyInfo(provider_id=key_namespace, key_info=key_name) + def __attrs_post_init__(self): + # type: () -> None + """Prepares initial values not handled by attrs.""" + self._key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name) def on_encrypt(self, encryption_materials): + # type: (EncryptionMaterials) -> EncryptionMaterials """Generate a data key if not present and encrypt it using any available wrapping key. :param encryption_materials: Encryption materials for the keyring to modify. @@ -217,12 +287,15 @@ def on_encrypt(self, encryption_materials): :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ encryption_materials = on_encrypt_helper( - encryption_materials, self._key_provider, self._wrapping_key, self._wrapping_algorithm, self.key_name + encryption_materials=encryption_materials, key_provider=self._key_provider, + wrapping_key=self._wrapping_key, wrapping_algorithm=self._wrapping_algorithm, + key_name=self.key_name ) return encryption_materials def on_decrypt(self, decryption_materials, encrypted_data_keys): + # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials """Attempt to decrypt the encrypted data keys. :param decryption_materials: Decryption materials for the keyring to modify. @@ -233,10 +306,12 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials """ # Decrypt data key - if encrypted_data_keys.key_provider == self._key_provider: - - decryption_materials = on_decrypt_helper( - decryption_materials, self._wrapping_key, self._wrapping_algorithm, self.key_name, encrypted_data_keys - ) + for key in encrypted_data_keys: + if key.key_provider == self._key_provider: + decryption_materials = on_decrypt_helper( + decryption_materials=decryption_materials, key_provider=self._key_provider, + wrapping_key=self._wrapping_key, wrapping_algorithm=self._wrapping_algorithm, + key_name=self.key_name, encrypted_data_key=key + ) return decryption_materials From d8a8389e9bbf480b5e94bef026cb6bfe93ba197e Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Wed, 3 Jul 2019 09:24:19 -0700 Subject: [PATCH 023/110] Corrected tox and flake8 errors --- src/aws_encryption_sdk/keyring/raw_keyring.py | 119 +++++++++--------- 1 file changed, 62 insertions(+), 57 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 344920196..0831dc757 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -12,20 +12,21 @@ # language governing permissions and limitations under the License. """Resources required for Raw Keyrings.""" -import os import logging +import os import attr import six -from aws_encryption_sdk.internal.formatting.deserialize import deserialize_wrapped_key -from aws_encryption_sdk.internal.formatting.serialize import serialize_wrapped_key, serialize_raw_master_key_prefix from aws_encryption_sdk.exceptions import EncryptKeyError -from aws_encryption_sdk.identifiers import WrappingAlgorithm, EncryptionKeyType +from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey -from aws_encryption_sdk.keyring.base import Keyring -from aws_encryption_sdk.structures import MasterKeyInfo, RawDataKey, KeyringTrace +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.keyring.base import Keyring +from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials +from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey try: # Python 3.5.0 and 3.5.1 have incompatible typing modules from typing import Iterable # noqa pylint: disable=unused-import @@ -45,20 +46,19 @@ def get_key_info_prefix(key_namespace, key_name, wrapping_key): :return: Serialized key_info prefix :rtype: bytes """ - key_info_prefix = serialize_raw_master_key_prefix(RawMasterKey(provider_id=key_namespace, - key_id=key_name, - wrapping_key=wrapping_key - ) - ) + key_info_prefix = serialize_raw_master_key_prefix( + RawMasterKey(provider_id=key_namespace, key_id=key_name, wrapping_key=wrapping_key) + ) return key_info_prefix -def on_encrypt_helper(encryption_materials, # type: EncryptionMaterials - key_provider, # type: MasterKeyInfo - wrapping_key, # type: WrappingKey - wrapping_algorithm, # type: WrappingAlgorithm - key_name # type: bytes - ): +def on_encrypt_helper( + encryption_materials, # type: EncryptionMaterials + key_provider, # type: MasterKeyInfo + wrapping_key, # type: WrappingKey + wrapping_algorithm, # type: WrappingAlgorithm + key_name, # type: bytes +): # type: (...) -> EncryptionMaterials """Helper function for the on_encrypt function of keyring. @@ -75,10 +75,7 @@ def on_encrypt_helper(encryption_materials, # type: EncryptionMaterials :rtype encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials """ # Create a keyring trace - keyring_trace = KeyringTrace( - wrapping_key=key_provider, - flags=set() - ) + keyring_trace = KeyringTrace(wrapping_key=key_provider, flags=set()) # Check if data key already exists if not encryption_materials.data_encryption_key: @@ -118,13 +115,14 @@ def on_encrypt_helper(encryption_materials, # type: EncryptionMaterials return encryption_materials -def on_decrypt_helper(decryption_materials, # type: DecryptionMaterials - key_provider, # type: MasterKeyInfo - wrapping_key, # type: WrappingKey - wrapping_algorithm, # type: WrappingAlgorithm - key_name, # type: bytes - encrypted_data_key # type: EncryptedDataKey - ): +def on_decrypt_helper( + decryption_materials, # type: DecryptionMaterials + key_provider, # type: MasterKeyInfo + wrapping_key, # type: WrappingKey + wrapping_algorithm, # type: WrappingAlgorithm + key_name, # type: bytes + encrypted_data_key, # type: EncryptedDataKey +): # type: (...) -> DecryptionMaterials """Helper function for the on_decrypt function of keyring. @@ -143,10 +141,7 @@ def on_decrypt_helper(decryption_materials, # type: DecryptionMaterials :rtype decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials """ # Create a keyring trace - keyring_trace = KeyringTrace( - wrapping_key=key_provider, - flags=set() - ) + keyring_trace = KeyringTrace(wrapping_key=key_provider, flags=set()) # Check if plaintext data key exists if decryption_materials.data_key: @@ -163,14 +158,12 @@ def on_decrypt_helper(decryption_materials, # type: DecryptionMaterials encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=decryption_materials.encryption_context ) except Exception as error: - logging.ERROR(error.__class__.__name__, ':', str(error)) + logging.ERROR(error.__class__.__name__, ":", str(error)) return decryption_materials # Update decryption materials data_encryption_key = RawDataKey( - key_provider=MasterKeyInfo(provider_id=key_provider.provider_id, - key_info=key_name), - data_key=plaintext_data_key + key_provider=MasterKeyInfo(provider_id=key_provider.provider_id, key_info=key_name), data_key=plaintext_data_key ) decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) @@ -199,14 +192,15 @@ def __attrs_post_init__(self): """Prepares initial values not handled by attrs.""" self._key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name) - self._key_info_prefix = get_key_info_prefix(key_namespace=self.key_namespace, - key_name=self.key_name, - wrapping_key=WrappingKey( - wrapping_algorithm=self._wrapping_algorithm, - wrapping_key=self._wrapping_key, - wrapping_key_type=EncryptionKeyType.SYMMETRIC - ) - ) + self._key_info_prefix = get_key_info_prefix( + key_namespace=self.key_namespace, + key_name=self.key_name, + wrapping_key=WrappingKey( + wrapping_algorithm=self._wrapping_algorithm, + wrapping_key=self._wrapping_key, + wrapping_key_type=EncryptionKeyType.SYMMETRIC, + ), + ) def on_encrypt(self, encryption_materials): # type: (EncryptionMaterials) -> EncryptionMaterials @@ -218,9 +212,11 @@ def on_encrypt(self, encryption_materials): :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ encryption_materials = on_encrypt_helper( - encryption_materials=encryption_materials, key_provider=self._key_provider, - wrapping_key=self._wrapping_key, wrapping_algorithm=self._wrapping_algorithm, - key_name=self.key_name + encryption_materials=encryption_materials, + key_provider=self._key_provider, + wrapping_key=self._wrapping_key, + wrapping_algorithm=self._wrapping_algorithm, + key_name=self.key_name, ) return encryption_materials @@ -239,14 +235,18 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): # Decrypt data key expected_key_info_len = len(self._key_info_prefix) + self._wrapping_algorithm.algorithm.iv_len for key in encrypted_data_keys: - if (key.key_provider.provider_id == self._key_provider.provider_id + if ( + key.key_provider.provider_id == self._key_provider.provider_id and len(key.key_provider.key_info) == expected_key_info_len and key.key_provider.key_info.startswith(self._key_info_prefix) ): decryption_materials = on_decrypt_helper( - decryption_materials=decryption_materials, key_provider=self._key_provider, - wrapping_key=self._wrapping_key, wrapping_algorithm=self._wrapping_algorithm, - key_name=self.key_name, encrypted_data_key=key + decryption_materials=decryption_materials, + key_provider=self._key_provider, + wrapping_key=self._wrapping_key, + wrapping_algorithm=self._wrapping_algorithm, + key_name=self.key_name, + encrypted_data_key=key, ) if decryption_materials.data_key: return decryption_materials @@ -287,9 +287,11 @@ def on_encrypt(self, encryption_materials): :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ encryption_materials = on_encrypt_helper( - encryption_materials=encryption_materials, key_provider=self._key_provider, - wrapping_key=self._wrapping_key, wrapping_algorithm=self._wrapping_algorithm, - key_name=self.key_name + encryption_materials=encryption_materials, + key_provider=self._key_provider, + wrapping_key=self._wrapping_key, + wrapping_algorithm=self._wrapping_algorithm, + key_name=self.key_name, ) return encryption_materials @@ -309,9 +311,12 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): for key in encrypted_data_keys: if key.key_provider == self._key_provider: decryption_materials = on_decrypt_helper( - decryption_materials=decryption_materials, key_provider=self._key_provider, - wrapping_key=self._wrapping_key, wrapping_algorithm=self._wrapping_algorithm, - key_name=self.key_name, encrypted_data_key=key + decryption_materials=decryption_materials, + key_provider=self._key_provider, + wrapping_key=self._wrapping_key, + wrapping_algorithm=self._wrapping_algorithm, + key_name=self.key_name, + encrypted_data_key=key, ) return decryption_materials From 8f9f73736ad519c736fe89e02b94d0166c389be7 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Mon, 8 Jul 2019 11:36:36 -0700 Subject: [PATCH 024/110] Minor change in raw-keyrings --- src/aws_encryption_sdk/keyring/raw_keyring.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 0831dc757..55762e684 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -254,6 +254,7 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): return decryption_materials +@attr.s class RawRSAKeyring(Keyring): """Public class for Raw RSA Keyring. From 9cd81ea0a4dec7466aa8f6d68742ecf026db86c3 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 18 Jun 2019 14:07:50 -0700 Subject: [PATCH 025/110] Adding Keyring API --- src/aws_encryption_sdk/keyring/__init__.py | 13 ++++++ src/aws_encryption_sdk/keyring/base.py | 40 +++++++++++++++++++ src/aws_encryption_sdk/keyring/raw_keyring.py | 0 3 files changed, 53 insertions(+) create mode 100644 src/aws_encryption_sdk/keyring/__init__.py create mode 100644 src/aws_encryption_sdk/keyring/base.py create mode 100644 src/aws_encryption_sdk/keyring/raw_keyring.py diff --git a/src/aws_encryption_sdk/keyring/__init__.py b/src/aws_encryption_sdk/keyring/__init__.py new file mode 100644 index 000000000..b9037ea16 --- /dev/null +++ b/src/aws_encryption_sdk/keyring/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2019 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. +"""All provided keyrings.""" diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py new file mode 100644 index 000000000..0d6b9000c --- /dev/null +++ b/src/aws_encryption_sdk/keyring/base.py @@ -0,0 +1,40 @@ +# Copyright 2017 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. +"""Base class interface for Keyrings.""" + + +class Keyring(object): + def on_encrypt(self, encryption_materials): + """Generates a data key and encrypts it using all wrapping keys the Keyring is associated with. + + :param encryption_materials: Contains signing key, encryption context and algorithm suite + required to encrypt data key + :type : aws_encryption_sdk.materials_managers.EncryptionMaterials + :returns encryption_materials: Contains signing key, unencrypted data key, encrypted data keys, + encryption context and algorithm suite required to encrypt data key + :rtype : aws_encryption_sdk.materials_managers.EncryptionMaterials + :raises AttributeError: if encryption materials not available + """ + raise NotImplementedError("Keyring does not implement on_encrypt function") + + def on_decrypt(self, decryption_materials): + """Tries to decrypt one of the keys in the list of encrypted data keys using wrapping keys + the Keyring is associated with. + + :param decryption_materials: Contains verification key, list of encrypted data keys. + :type : aws_encryption_sdk.materials_managers.DecryptionMaterials + :returns decryption_materials: Contains verification key, list of encrypted data keys and decrypted data key. + :rtype : aws_encryption_sdk.materials_managers.DecryptionMaterials + :raises AttributeError: if decryption materials not available + """ + raise NotImplementedError("Keyring does not implement on_decrypt function") diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py new file mode 100644 index 000000000..e69de29bb From e3d075733b90876954e96cba16b369f8f4d53dca Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 18 Jun 2019 14:51:28 -0700 Subject: [PATCH 026/110] Added docstring to public class --- src/aws_encryption_sdk/keyring/base.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index 0d6b9000c..575758edd 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -14,6 +14,8 @@ class Keyring(object): + """Parent interface for Keyring classes. + """ def on_encrypt(self, encryption_materials): """Generates a data key and encrypts it using all wrapping keys the Keyring is associated with. From fcb03c25f801b20b7a5427bf99a2347a70c46321 Mon Sep 17 00:00:00 2001 From: MeghaShetty Date: Tue, 18 Jun 2019 14:12:41 -0700 Subject: [PATCH 027/110] Delete __init__.py --- src/aws_encryption_sdk/keyring/__init__.py | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 src/aws_encryption_sdk/keyring/__init__.py diff --git a/src/aws_encryption_sdk/keyring/__init__.py b/src/aws_encryption_sdk/keyring/__init__.py deleted file mode 100644 index b9037ea16..000000000 --- a/src/aws_encryption_sdk/keyring/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2019 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. -"""All provided keyrings.""" From ae78331e43861fe765f5cbc64ae4440ef496986d Mon Sep 17 00:00:00 2001 From: MeghaShetty Date: Tue, 18 Jun 2019 14:12:53 -0700 Subject: [PATCH 028/110] Delete raw_keyring.py --- src/aws_encryption_sdk/keyring/raw_keyring.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/aws_encryption_sdk/keyring/raw_keyring.py diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py deleted file mode 100644 index e69de29bb..000000000 From f668ca4efb77323d5cceff4bb9654972b046407a Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 18 Jun 2019 15:36:18 -0700 Subject: [PATCH 029/110] Edited docstring --- src/aws_encryption_sdk/keyring/base.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index 575758edd..a1e77e905 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -16,6 +16,7 @@ class Keyring(object): """Parent interface for Keyring classes. """ + def on_encrypt(self, encryption_materials): """Generates a data key and encrypts it using all wrapping keys the Keyring is associated with. From c06b1fa695c753451b10e961382554f369dfb62b Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 18 Jun 2019 16:07:06 -0700 Subject: [PATCH 030/110] Edited docstring again --- src/aws_encryption_sdk/keyring/base.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index a1e77e905..88e3ae068 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -14,8 +14,7 @@ class Keyring(object): - """Parent interface for Keyring classes. - """ + """Parent interface for Keyring classes.""" def on_encrypt(self, encryption_materials): """Generates a data key and encrypts it using all wrapping keys the Keyring is associated with. From 1e2a6726b3d9d4330e8e27bf6c94a57d2702760a Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Wed, 19 Jun 2019 12:58:14 -0700 Subject: [PATCH 031/110] Changes in docstring statements --- src/aws_encryption_sdk/keyring/__init__.py | 13 ++++ src/aws_encryption_sdk/keyring/base.py | 5 +- src/aws_encryption_sdk/keyring/raw_keyring.py | 74 +++++++++++++++++++ 3 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 src/aws_encryption_sdk/keyring/__init__.py create mode 100644 src/aws_encryption_sdk/keyring/raw_keyring.py diff --git a/src/aws_encryption_sdk/keyring/__init__.py b/src/aws_encryption_sdk/keyring/__init__.py new file mode 100644 index 000000000..ada03b4d7 --- /dev/null +++ b/src/aws_encryption_sdk/keyring/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2017 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. +"""All provided Keyrings.""" diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index 88e3ae068..19f2ae169 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -17,7 +17,7 @@ class Keyring(object): """Parent interface for Keyring classes.""" def on_encrypt(self, encryption_materials): - """Generates a data key and encrypts it using all wrapping keys the Keyring is associated with. + """Generate a data key and encrypt it using all wrapping keys the Keyring is associated with. :param encryption_materials: Contains signing key, encryption context and algorithm suite required to encrypt data key @@ -30,8 +30,7 @@ def on_encrypt(self, encryption_materials): raise NotImplementedError("Keyring does not implement on_encrypt function") def on_decrypt(self, decryption_materials): - """Tries to decrypt one of the keys in the list of encrypted data keys using wrapping keys - the Keyring is associated with. + """Attempt to decrypt the encrypted data keys. :param decryption_materials: Contains verification key, list of encrypted data keys. :type : aws_encryption_sdk.materials_managers.DecryptionMaterials diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py new file mode 100644 index 000000000..30d2bbd5a --- /dev/null +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -0,0 +1,74 @@ +# Copyright 2017 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. +"""Resources required for Raw Keyrings.""" +import os +import attr + +import aws_encryption_sdk.internal.formatting.deserialize +import aws_encryption_sdk.internal.formatting.serialize +from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey +from aws_encryption_sdk.keyring.base import Keyring +from aws_encryption_sdk.structures import DataKey, RawDataKey + + +class RawAESKeyring(Keyring): + """Public class for Raw AES Keyring.""" + + def on_encrypt(self, encryption_materials): + # Generate data key + plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) + + # Encrypt data key + wrapping_key = attr.ib(hash=True, validator=attr.validators.instance_of(WrappingKey)) + encrypted_wrapped_key = wrapping_key.encrypt( + plaintext_data_key=plaintext_data_key, + encryption_context=encryption_materials.encryption_context + ) + encrypted_data_key = aws_encryption_sdk.internal.formatting.serialize.serialize_wrapped_key( + # WHAAAAT + key_provider=self.key_provider, + wrapping_algorithm=wrapping_key.wrapping_algorithm, + # WHAAAAT + wrapping_key_id=self.key_id, + encrypted_wrapped_key=encrypted_wrapped_key, + ) + + # Update keyring trace + + # Update encryption materials + encryption_materials.data_encryption_key = RawDataKey( + # WHAAAAT + key_provider=self.key_provider, + data_key=plaintext_data_key + ) + encryption_materials.encrypted_data_keys.add(encrypted_data_key) + + return encryption_materials + + def on_decrypt(self, decryption_materials): + # Decrypt data key + + + # Update keyring trace + + return decryption_materials + + +class RawRSAKeyring(Keyring): + """Public class for Raw RSA Keyring.""" + + def on_encrypt(self, encryption_materials): + return encryption_materials + + def on_decrypt(self, decryption_materials): + return decryption_materials From 82feb006e101f92ae6acff7b34e5a49b4a816440 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Wed, 19 Jun 2019 13:06:19 -0700 Subject: [PATCH 032/110] Docstring changes --- src/aws_encryption_sdk/keyring/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index 19f2ae169..cdec0842a 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -17,7 +17,7 @@ class Keyring(object): """Parent interface for Keyring classes.""" def on_encrypt(self, encryption_materials): - """Generate a data key and encrypt it using all wrapping keys the Keyring is associated with. + """Generate a data key if not present and encrypt it using any available wrapping key. :param encryption_materials: Contains signing key, encryption context and algorithm suite required to encrypt data key From 11f9ce62aeb10af5ad9a97cfbef19b4b24465792 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 20 Jun 2019 13:53:32 -0700 Subject: [PATCH 033/110] Changes in docstring --- src/aws_encryption_sdk/keyring/base.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index cdec0842a..3c4689d70 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -21,11 +21,11 @@ def on_encrypt(self, encryption_materials): :param encryption_materials: Contains signing key, encryption context and algorithm suite required to encrypt data key - :type : aws_encryption_sdk.materials_managers.EncryptionMaterials - :returns encryption_materials: Contains signing key, unencrypted data key, encrypted data keys, + :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials + :returns: Contains signing key, unencrypted data key, encrypted data keys, encryption context and algorithm suite required to encrypt data key - :rtype : aws_encryption_sdk.materials_managers.EncryptionMaterials - :raises AttributeError: if encryption materials not available + :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials + :raises NotImplementedError: if method is not implemented """ raise NotImplementedError("Keyring does not implement on_encrypt function") @@ -33,9 +33,9 @@ def on_decrypt(self, decryption_materials): """Attempt to decrypt the encrypted data keys. :param decryption_materials: Contains verification key, list of encrypted data keys. - :type : aws_encryption_sdk.materials_managers.DecryptionMaterials - :returns decryption_materials: Contains verification key, list of encrypted data keys and decrypted data key. - :rtype : aws_encryption_sdk.materials_managers.DecryptionMaterials - :raises AttributeError: if decryption materials not available + :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials + :returns: Contains verification key, list of encrypted data keys and decrypted data key. + :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials + :raises NotImplementedError: if method is not implemented """ raise NotImplementedError("Keyring does not implement on_decrypt function") From 7a345a57e0aa5f2be72910c5ccc9c72647af3329 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 20 Jun 2019 14:16:36 -0700 Subject: [PATCH 034/110] Raw keyring initial --- src/aws_encryption_sdk/keyring/raw_keyring.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 30d2bbd5a..2a853a462 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -12,6 +12,7 @@ # language governing permissions and limitations under the License. """Resources required for Raw Keyrings.""" import os + import attr import aws_encryption_sdk.internal.formatting.deserialize @@ -31,8 +32,7 @@ def on_encrypt(self, encryption_materials): # Encrypt data key wrapping_key = attr.ib(hash=True, validator=attr.validators.instance_of(WrappingKey)) encrypted_wrapped_key = wrapping_key.encrypt( - plaintext_data_key=plaintext_data_key, - encryption_context=encryption_materials.encryption_context + plaintext_data_key=plaintext_data_key, encryption_context=encryption_materials.encryption_context ) encrypted_data_key = aws_encryption_sdk.internal.formatting.serialize.serialize_wrapped_key( # WHAAAAT @@ -49,7 +49,7 @@ def on_encrypt(self, encryption_materials): encryption_materials.data_encryption_key = RawDataKey( # WHAAAAT key_provider=self.key_provider, - data_key=plaintext_data_key + data_key=plaintext_data_key, ) encryption_materials.encrypted_data_keys.add(encrypted_data_key) @@ -58,7 +58,6 @@ def on_encrypt(self, encryption_materials): def on_decrypt(self, decryption_materials): # Decrypt data key - # Update keyring trace return decryption_materials From 6ef9ea77fb0384311b68b493a5659e01b3a74154 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 20 Jun 2019 14:19:54 -0700 Subject: [PATCH 035/110] Raw keyring encrypt commit --- requirements.txt | 1 + src/aws_encryption_sdk/keyring/raw_keyring.py | 28 +++++++++++++------ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/requirements.txt b/requirements.txt index f04114485..7540d66bf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +six boto3>=1.4.4 cryptography>=1.8.1 attrs>=17.4.0 diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 2a853a462..a2ab060bb 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -18,27 +18,38 @@ import aws_encryption_sdk.internal.formatting.deserialize import aws_encryption_sdk.internal.formatting.serialize from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey +from aws_encryption_sdk.identifiers import WrappingAlgorithm from aws_encryption_sdk.keyring.base import Keyring -from aws_encryption_sdk.structures import DataKey, RawDataKey +from aws_encryption_sdk.structures import DataKey, RawDataKey, MasterKeyInfo +@attr.s class RawAESKeyring(Keyring): """Public class for Raw AES Keyring.""" + provider_id = attr.ib(validator=attr.validators.instance_of(str)) + key_id = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) + wrapping_key = attr.ib(hash=True, validator=attr.validators.instance_of(WrappingKey)) + wrapping_algorithm = attr.ib(validator=attr.validators.instance_of(WrappingAlgorithm)) + + key_provider = MasterKeyInfo( + provider_id=provider_id, + key_info=key_id + ) + def on_encrypt(self, encryption_materials): # Generate data key plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) # Encrypt data key - wrapping_key = attr.ib(hash=True, validator=attr.validators.instance_of(WrappingKey)) - encrypted_wrapped_key = wrapping_key.encrypt( - plaintext_data_key=plaintext_data_key, encryption_context=encryption_materials.encryption_context + encrypted_wrapped_key = self.wrapping_key.encrypt( + plaintext_data_key=plaintext_data_key, + encryption_context=encryption_materials.encryption_context ) + encrypted_data_key = aws_encryption_sdk.internal.formatting.serialize.serialize_wrapped_key( - # WHAAAAT key_provider=self.key_provider, - wrapping_algorithm=wrapping_key.wrapping_algorithm, - # WHAAAAT + wrapping_algorithm=self.wrapping_algorithm, wrapping_key_id=self.key_id, encrypted_wrapped_key=encrypted_wrapped_key, ) @@ -47,7 +58,6 @@ def on_encrypt(self, encryption_materials): # Update encryption materials encryption_materials.data_encryption_key = RawDataKey( - # WHAAAAT key_provider=self.key_provider, data_key=plaintext_data_key, ) @@ -71,3 +81,5 @@ def on_encrypt(self, encryption_materials): def on_decrypt(self, decryption_materials): return decryption_materials + + From 65767313c273e9a4c1fe0ec8e567c11dcee92a70 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 20 Jun 2019 16:17:06 -0700 Subject: [PATCH 036/110] Encrypt functions for Raw RSA and AES --- src/aws_encryption_sdk/keyring/raw_keyring.py | 53 +++++++++++++------ 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index a2ab060bb..9bc5ad03e 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -17,25 +17,22 @@ import aws_encryption_sdk.internal.formatting.deserialize import aws_encryption_sdk.internal.formatting.serialize -from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey from aws_encryption_sdk.identifiers import WrappingAlgorithm +from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey from aws_encryption_sdk.keyring.base import Keyring -from aws_encryption_sdk.structures import DataKey, RawDataKey, MasterKeyInfo +from aws_encryption_sdk.structures import DataKey, MasterKeyInfo, RawDataKey @attr.s class RawAESKeyring(Keyring): """Public class for Raw AES Keyring.""" - provider_id = attr.ib(validator=attr.validators.instance_of(str)) - key_id = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) + key_namespace = attr.ib(validator=attr.validators.instance_of(str)) + key_name = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) wrapping_key = attr.ib(hash=True, validator=attr.validators.instance_of(WrappingKey)) wrapping_algorithm = attr.ib(validator=attr.validators.instance_of(WrappingAlgorithm)) - key_provider = MasterKeyInfo( - provider_id=provider_id, - key_info=key_id - ) + key_provider = MasterKeyInfo(provider_id=key_namespace, key_info=key_name) def on_encrypt(self, encryption_materials): # Generate data key @@ -43,14 +40,13 @@ def on_encrypt(self, encryption_materials): # Encrypt data key encrypted_wrapped_key = self.wrapping_key.encrypt( - plaintext_data_key=plaintext_data_key, - encryption_context=encryption_materials.encryption_context + plaintext_data_key=plaintext_data_key, encryption_context=encryption_materials.encryption_context ) encrypted_data_key = aws_encryption_sdk.internal.formatting.serialize.serialize_wrapped_key( key_provider=self.key_provider, wrapping_algorithm=self.wrapping_algorithm, - wrapping_key_id=self.key_id, + wrapping_key_id=self.key_name, encrypted_wrapped_key=encrypted_wrapped_key, ) @@ -58,8 +54,7 @@ def on_encrypt(self, encryption_materials): # Update encryption materials encryption_materials.data_encryption_key = RawDataKey( - key_provider=self.key_provider, - data_key=plaintext_data_key, + key_provider=self.key_provider, data_key=plaintext_data_key ) encryption_materials.encrypted_data_keys.add(encrypted_data_key) @@ -76,10 +71,38 @@ def on_decrypt(self, decryption_materials): class RawRSAKeyring(Keyring): """Public class for Raw RSA Keyring.""" + key_namespace = attr.ib(validator=attr.validators.instance_of(str)) + key_name = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) + wrapping_key = attr.ib(hash=True, validator=attr.validators.instance_of(WrappingKey)) + wrapping_algorithm = attr.ib(validator=attr.validators.instance_of(WrappingAlgorithm)) + + key_provider = MasterKeyInfo(provider_id=key_namespace, key_info=key_name) + def on_encrypt(self, encryption_materials): + # Generate data key + plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) + + # Encrypt data key + encrypted_wrapped_key = self.wrapping_key.encrypt( + plaintext_data_key=plaintext_data_key, encryption_context=encryption_materials.encryption_context + ) + + encrypted_data_key = aws_encryption_sdk.internal.formatting.serialize.serialize_wrapped_key( + key_provider=self.key_provider, + wrapping_algorithm=self.wrapping_algorithm, + wrapping_key_id=self.key_name, + encrypted_wrapped_key=encrypted_wrapped_key, + ) + + # Update keyring trace + + # Update encryption materials + encryption_materials.data_encryption_key = RawDataKey( + key_provider=self.key_provider, data_key=plaintext_data_key + ) + encryption_materials.encrypted_data_keys.add(encrypted_data_key) + return encryption_materials def on_decrypt(self, decryption_materials): return decryption_materials - - From 5a87c0e702e3f05aff8440eaf842af9e7f2a2c63 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 20 Jun 2019 16:59:54 -0700 Subject: [PATCH 037/110] Raw RSA and AES initial --- src/aws_encryption_sdk/keyring/raw_keyring.py | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 9bc5ad03e..74e19c653 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -12,6 +12,7 @@ # language governing permissions and limitations under the License. """Resources required for Raw Keyrings.""" import os +import struct import attr @@ -19,6 +20,7 @@ import aws_encryption_sdk.internal.formatting.serialize from aws_encryption_sdk.identifiers import WrappingAlgorithm from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey +from aws_encryption_sdk.internal.str_ops import to_bytes from aws_encryption_sdk.keyring.base import Keyring from aws_encryption_sdk.structures import DataKey, MasterKeyInfo, RawDataKey @@ -34,7 +36,25 @@ class RawAESKeyring(Keyring): key_provider = MasterKeyInfo(provider_id=key_namespace, key_info=key_name) + key_info_prefix = struct.pack( + ">{}sII".format(len(key_name)), + to_bytes(key_name), + # Tag Length is stored in bits, not bytes + wrapping_algorithm.algorithm.tag_len * 8, + wrapping_algorithm.algorithm.iv_len, + ) + def on_encrypt(self, encryption_materials): + """Generate a data key if not present and encrypt it using any available wrapping key. + + :param encryption_materials: Contains signing key, encryption context and algorithm suite + required to encrypt data key + :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials + :returns: Contains signing key, unencrypted data key, encrypted data keys, + encryption context and algorithm suite required to encrypt data key + :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials + """ + # Generate data key plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) @@ -61,7 +81,35 @@ def on_encrypt(self, encryption_materials): return encryption_materials def on_decrypt(self, decryption_materials): + """Attempt to decrypt the encrypted data keys. + + :param decryption_materials: Contains verification key, list of encrypted data keys. + :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials + :returns: Contains verification key, list of encrypted data keys and decrypted data key. + :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials + """ + # Decrypt data key + expected_key_info_len = len(self.key_info_prefix) + self.wrapping_algorithm.algorithm.iv_len + if ( + decryption_materials.encrypted_data_key.key_provider.provider_id == self.key_provider.provider_id + and len(decryption_materials.encrypted_data_key.key_provider.key_info) == expected_key_info_len + and decryption_materials.encrypted_data_key.key_provider.key_info.startswith(self.key_info_prefix) + ): + encrypted_wrapped_key = aws_encryption_sdk.internal.formatting.deserialize.deserialize_wrapped_key( + wrapping_algorithm=self.wrapping_algorithm, + wrapping_key_id=self.key_name, + wrapped_encrypted_key=decryption_materials.encrypted_data_key, + ) + plaintext_data_key = self.wrapping_key.decrypt( + encrypted_wrapped_data_key=encrypted_wrapped_key, + encryption_context=decryption_materials.encryption_context, + ) + decryption_materials.data_key = DataKey( + key_provider=decryption_materials.encrypted_data_key.key_provider, + data_key=plaintext_data_key, + encrypted_data_key=decryption_materials.encrypted_data_key.encrypted_data_key, + ) # Update keyring trace @@ -79,6 +127,16 @@ class RawRSAKeyring(Keyring): key_provider = MasterKeyInfo(provider_id=key_namespace, key_info=key_name) def on_encrypt(self, encryption_materials): + """Generate a data key if not present and encrypt it using any available wrapping key. + + :param encryption_materials: Contains signing key, encryption context and algorithm suite + required to encrypt data key + :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials + :returns: Contains signing key, unencrypted data key, encrypted data keys, + encryption context and algorithm suite required to encrypt data key + :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials + """ + # Generate data key plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) @@ -105,4 +163,30 @@ def on_encrypt(self, encryption_materials): return encryption_materials def on_decrypt(self, decryption_materials): + """Attempt to decrypt the encrypted data keys. + + :param decryption_materials: Contains verification key, list of encrypted data keys. + :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials + :returns: Contains verification key, list of encrypted data keys and decrypted data key. + :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials + """ + + # Decrypt data key + if decryption_materials.encrypted_data_key.key_provider == self.key_provider: + encrypted_wrapped_key = aws_encryption_sdk.internal.formatting.deserialize.deserialize_wrapped_key( + wrapping_algorithm=self.wrapping_algorithm, + wrapping_key_id=self.key_name, + wrapped_encrypted_key=decryption_materials.encrypted_data_key, + ) + plaintext_data_key = self.wrapping_key.decrypt( + encrypted_wrapped_data_key=encrypted_wrapped_key, + encryption_context=decryption_materials.encryption_context, + ) + decryption_materials.data_key = DataKey( + key_provider=decryption_materials.encrypted_data_key.key_provider, + data_key=plaintext_data_key, + encrypted_data_key=decryption_materials.encrypted_data_key.encrypted_data_key, + ) + + # Update keyring trace return decryption_materials From dd01e6b79d738d208f8f79aae12d896f5e4a8a5f Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Thu, 20 Jun 2019 17:36:09 -0700 Subject: [PATCH 038/110] bump attrs to 19.1.0 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 7540d66bf..8378d126e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ six boto3>=1.4.4 cryptography>=1.8.1 -attrs>=17.4.0 +attrs>=19.1.0 wrapt>=1.10.11 \ No newline at end of file From 82429fe3b8abb1cf6ecad12146f04c390bc3c37d Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Thu, 20 Jun 2019 17:36:54 -0700 Subject: [PATCH 039/110] add keyring trace and integrate into updated encrytion/decryption materials --- src/aws_encryption_sdk/identifiers.py | 10 ++ .../materials_managers/__init__.py | 150 +++++++++++++++--- src/aws_encryption_sdk/structures.py | 16 ++ test/unit/test_material_managers.py | 76 +++++++-- test/unit/test_material_managers_default.py | 6 +- 5 files changed, 217 insertions(+), 41 deletions(-) diff --git a/src/aws_encryption_sdk/identifiers.py b/src/aws_encryption_sdk/identifiers.py index 1bd9bb1f1..0add9724d 100644 --- a/src/aws_encryption_sdk/identifiers.py +++ b/src/aws_encryption_sdk/identifiers.py @@ -328,3 +328,13 @@ 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.""" + + WRAPPING_KEY_GENERATED_DATA_KEY = 1 + WRAPPING_KEY_ENCRYPTED_DATA_KEY = 2 + WRAPPING_KEY_DECRYPTED_DATA_KEY = 3 + WRAPPING_KEY_SIGNED_ENC_CTX = 4 + WRAPPING_KEY_VERIFIED_ENC_CTX = 5 diff --git a/src/aws_encryption_sdk/materials_managers/__init__.py b/src/aws_encryption_sdk/materials_managers/__init__.py index bc5230c51..18ebd7898 100644 --- a/src/aws_encryption_sdk/materials_managers/__init__.py +++ b/src/aws_encryption_sdk/materials_managers/__init__.py @@ -16,10 +16,11 @@ """ import attr import six +from attr.validators import deep_iterable, deep_mapping, instance_of, optional -from ..identifiers import Algorithm +from ..identifiers import Algorithm, KeyRingTraceFlag from ..internal.utils.streams import ROStream -from ..structures import DataKey +from ..structures import DataKey, EncryptedDataKey, KeyRingTrace @attr.s(hash=False) @@ -51,28 +52,87 @@ class EncryptionMaterialsRequest(object): ) -@attr.s(hash=False) -class EncryptionMaterials(object): +@attr.s +class CryptographicMaterials(object): + """Cryptographic materials core. + + .. versionadded:: 1.5.0 + + :param Algorithm algorithm: Algorithm to use for encrypting message + :param dict encryption_context: Encryption context tied to `encrypted_data_keys` + :param DataKey data_encryption_key: Plaintext data key to use for encrypting message + :param encrypted_data_keys: List of encrypted data keys + :type encrypted_data_keys: list of :class:`EncryptedDataKey` + :param keyring_trace: Any KeyRing trace entries + :type keyring_trace: list of :class:`KeyRingTrace` + """ + + algorithm = attr.ib(validator=optional(instance_of(Algorithm))) + encryption_context = attr.ib( + validator=optional( + deep_mapping(key_validator=instance_of(six.string_types), value_validator=instance_of(six.string_types)) + ) + ) + data_encryption_key = attr.ib(default=None, validator=optional(instance_of(DataKey))) + encrypted_data_keys = attr.ib( + default=attr.Factory(list), validator=optional(deep_iterable(member_validator=instance_of(EncryptedDataKey))) + ) + keyring_trace = attr.ib( + default=attr.Factory(list), validator=optional(deep_iterable(member_validator=instance_of(KeyRingTrace))) + ) + + +@attr.s(hash=False, init=False) +class EncryptionMaterials(CryptographicMaterials): """Encryption materials returned by a crypto material manager's `get_encryption_materials` method. .. versionadded:: 1.3.0 - :param algorithm: Algorithm to use for encrypting message - :type algorithm: aws_encryption_sdk.identifiers.Algorithm - :param data_encryption_key: Plaintext data key to use for encrypting message - :type data_encryption_key: aws_encryption_sdk.structures.DataKey - :param encrypted_data_keys: List of encrypted data keys - :type encrypted_data_keys: list of `aws_encryption_sdk.structures.EncryptedDataKey` + .. versionadded:: 1.5.0 + + The **keyring_trace** parameter. + + .. versionadded:: 1.5.0 + + Most parameters are now optional. + + :param Algorithm algorithm: Algorithm to use for encrypting message + :param DataKey data_encryption_key: Plaintext data key to use for encrypting message (optional) + :param encrypted_data_keys: List of encrypted data keys (optional) + :type encrypted_data_keys: list of :class:`EncryptedDataKey` :param dict encryption_context: Encryption context tied to `encrypted_data_keys` - :param bytes signing_key: Encoded signing key + :param bytes signing_key: Encoded signing key (optional) + :param keyring_trace: Any KeyRing trace entries (optional) + :type keyring_trace: list of :class:`KeyRingTrace` """ - algorithm = attr.ib(validator=attr.validators.instance_of(Algorithm)) - data_encryption_key = attr.ib(validator=attr.validators.instance_of(DataKey)) - encrypted_data_keys = attr.ib(validator=attr.validators.instance_of(set)) - encryption_context = attr.ib(validator=attr.validators.instance_of(dict)) signing_key = attr.ib(default=None, validator=attr.validators.optional(attr.validators.instance_of(bytes))) + def __init__( + self, + algorithm=None, + data_encryption_key=None, + encrypted_data_keys=None, + encryption_context=None, + signing_key=None, + **kwargs + ): + if algorithm is None: + raise TypeError("algorithm must not be None") + + if encryption_context is None: + raise TypeError("encryption_context must not be None") + + super(EncryptionMaterials, self).__init__( + algorithm=algorithm, + encryption_context=encryption_context, + data_encryption_key=data_encryption_key, + encrypted_data_keys=encrypted_data_keys, + **kwargs + ) + self.signing_key = signing_key + attr.validate(self) + @attr.s(hash=False) class DecryptionMaterialsRequest(object): @@ -92,16 +152,64 @@ class DecryptionMaterialsRequest(object): encryption_context = attr.ib(validator=attr.validators.instance_of(dict)) -@attr.s(hash=False) -class DecryptionMaterials(object): +_DEFAULT_SENTINEL = object() + + +@attr.s(hash=False, init=False) +class DecryptionMaterials(CryptographicMaterials): """Decryption materials returned by a crypto material manager's `decrypt_materials` method. .. versionadded:: 1.3.0 - :param data_key: Plaintext data key to use with message decryption - :type data_key: aws_encryption_sdk.structures.DataKey - :param bytes verification_key: Raw signature verification key + .. versionadded:: 1.5.0 + + The **algorithm**, **data_encryption_key**, **encrypted_data_keys**, + **encryption_context**, and **keyring_trace** parameters. + + .. versionadded:: 1.5.0 + + All parameters are now optional. + + :param Algorithm algorithm: Algorithm to use for encrypting message (optional) + :param DataKey data_encryption_key: Plaintext data key to use for encrypting message (optional) + :param encrypted_data_keys: List of encrypted data keys (optional) + :type encrypted_data_keys: list of :class:`EncryptedDataKey` + :param dict encryption_context: Encryption context tied to `encrypted_data_keys` (optional) + :param bytes verification_key: Raw signature verification key (optional) + :param keyring_trace: Any KeyRing trace entries (optional) + :type keyring_trace: list of :class:`KeyRingTrace` """ - data_key = attr.ib(validator=attr.validators.instance_of(DataKey)) verification_key = attr.ib(default=None, validator=attr.validators.optional(attr.validators.instance_of(bytes))) + + def __init__(self, data_key=_DEFAULT_SENTINEL, verification_key=None, **kwargs): + if any( + ( + data_key is _DEFAULT_SENTINEL and "data_encryption_key" not in kwargs, + data_key is not _DEFAULT_SENTINEL and "data_encryption_key" in kwargs, + ) + ): + raise TypeError("Exactly one of data_key or data_encryption_key must be set") + + if data_key is not _DEFAULT_SENTINEL and "data_encryption_key" not in kwargs: + kwargs["data_encryption_key"] = data_key + + for legacy_missing in ("algorithm", "encryption_context"): + if legacy_missing not in kwargs: + kwargs[legacy_missing] = None + + super(DecryptionMaterials, self).__init__(**kwargs) + + self.verification_key = verification_key + attr.validate(self) + + @property + def data_key(self): + """Backwards-compatible shim.""" + return self.data_encryption_key + + @data_key.setter + def data_key(self, value): + # type: (DataKey) -> None + """Backwards-compatible shim.""" + self.data_encryption_key = value diff --git a/src/aws_encryption_sdk/structures.py b/src/aws_encryption_sdk/structures.py index 8229d65fb..86b87b932 100644 --- a/src/aws_encryption_sdk/structures.py +++ b/src/aws_encryption_sdk/structures.py @@ -13,6 +13,7 @@ """Public data structures for aws_encryption_sdk.""" import attr import six +from attr.validators import deep_iterable, instance_of import aws_encryption_sdk.identifiers from aws_encryption_sdk.internal.str_ops import to_bytes, to_str @@ -104,3 +105,18 @@ class EncryptedDataKey(object): key_provider = attr.ib(hash=True, validator=attr.validators.instance_of(MasterKeyInfo)) encrypted_data_key = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) + + +@attr.s +class KeyRingTrace(object): + """Record of all actions that a KeyRing performed with a wrapping key. + + :param MasterKeyInfo wrapping_key: Wrapping key used + :param flags: Actions performed + :type flags: set of :class:`KeyRingTraceFlag` + """ + + wrapping_key = attr.ib(validator=instance_of(MasterKeyInfo)) + flags = attr.ib( + validator=deep_iterable(member_validator=instance_of(aws_encryption_sdk.identifiers.KeyRingTraceFlag)) + ) diff --git a/test/unit/test_material_managers.py b/test/unit/test_material_managers.py index fcd4977f5..9eb32a125 100644 --- a/test/unit/test_material_managers.py +++ b/test/unit/test_material_managers.py @@ -12,66 +12,93 @@ # language governing permissions and limitations under the License. """Test suite for aws_encryption_sdk.materials_managers""" import pytest -from mock import MagicMock +from mock import MagicMock, sentinel from pytest_mock import mocker # noqa pylint: disable=unused-import -from aws_encryption_sdk.identifiers import Algorithm +from aws_encryption_sdk.identifiers import KeyRingTraceFlag +from aws_encryption_sdk.internal.defaults import ALGORITHM from aws_encryption_sdk.internal.utils.streams import ROStream from aws_encryption_sdk.materials_managers import ( + CryptographicMaterials, DecryptionMaterials, DecryptionMaterialsRequest, EncryptionMaterials, EncryptionMaterialsRequest, ) -from aws_encryption_sdk.structures import DataKey +from aws_encryption_sdk.structures import DataKey, KeyRingTrace, MasterKeyInfo pytestmark = [pytest.mark.unit, pytest.mark.local] +_DATA_KEY = DataKey( + key_provider=MasterKeyInfo(provider_id="Provider", key_info=b"Info"), + data_key=b"1234567890123456789012", + encrypted_data_key=b"asdf", +) _VALID_KWARGS = { + "CryptographicMaterials": dict( + algorithm=ALGORITHM, + encryption_context={"additional": "data"}, + data_encryption_key=_DATA_KEY, + encrypted_data_keys=[], + keyring_trace=[ + KeyRingTrace( + wrapping_key=MasterKeyInfo(provider_id="Provider", key_info=b"Info"), + flags={KeyRingTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}, + ) + ], + ), "EncryptionMaterialsRequest": dict( encryption_context={}, plaintext_rostream=MagicMock(__class__=ROStream), frame_length=5, - algorithm=MagicMock(__class__=Algorithm), + algorithm=ALGORITHM, plaintext_length=5, ), "EncryptionMaterials": dict( - algorithm=MagicMock(__class__=Algorithm), - data_encryption_key=MagicMock(__class__=DataKey), + algorithm=ALGORITHM, + data_encryption_key=_DATA_KEY, encrypted_data_keys=set([]), encryption_context={}, signing_key=b"", ), - "DecryptionMaterialsRequest": dict( - algorithm=MagicMock(__class__=Algorithm), encrypted_data_keys=set([]), encryption_context={} + "DecryptionMaterialsRequest": dict(algorithm=ALGORITHM, encrypted_data_keys=set([]), encryption_context={}), + "DecryptionMaterials": dict( + data_key=_DATA_KEY, verification_key=b"ex_verification_key", algorithm=ALGORITHM, encryption_context={} ), - "DecryptionMaterials": dict(data_key=MagicMock(__class__=DataKey), verification_key=b"ex_verification_key"), } +_REMOVE = object() @pytest.mark.parametrize( "attr_class, invalid_kwargs", ( + (CryptographicMaterials, dict(algorithm=1234)), + (CryptographicMaterials, dict(encryption_context=1234)), + (CryptographicMaterials, dict(data_encryption_key=1234)), + (CryptographicMaterials, dict(encrypted_data_keys=1234)), + (CryptographicMaterials, dict(keyring_trace=1234)), (EncryptionMaterialsRequest, dict(encryption_context=None)), (EncryptionMaterialsRequest, dict(frame_length="not an int")), (EncryptionMaterialsRequest, dict(algorithm="not an Algorithm or None")), (EncryptionMaterialsRequest, dict(plaintext_length="not an int or None")), (EncryptionMaterials, dict(algorithm=None)), - (EncryptionMaterials, dict(data_encryption_key=None)), - (EncryptionMaterials, dict(encrypted_data_keys=None)), (EncryptionMaterials, dict(encryption_context=None)), (EncryptionMaterials, dict(signing_key=u"not bytes or None")), (DecryptionMaterialsRequest, dict(algorithm=None)), (DecryptionMaterialsRequest, dict(encrypted_data_keys=None)), (DecryptionMaterialsRequest, dict(encryption_context=None)), - (DecryptionMaterials, dict(data_key=None)), (DecryptionMaterials, dict(verification_key=5555)), + (DecryptionMaterials, dict(data_key=_DATA_KEY, data_encryption_key=_DATA_KEY)), + (DecryptionMaterials, dict(data_key=_REMOVE, data_encryption_key=_REMOVE)), ), ) def test_attributes_fails(attr_class, invalid_kwargs): kwargs = _VALID_KWARGS[attr_class.__name__].copy() kwargs.update(invalid_kwargs) + purge_keys = [key for key, val in kwargs.items() if val is _REMOVE] + for key in purge_keys: + del kwargs[key] with pytest.raises(TypeError): attr_class(**kwargs) @@ -85,14 +112,29 @@ def test_encryption_materials_request_attributes_defaults(): def test_encryption_materials_defaults(): test = EncryptionMaterials( - algorithm=MagicMock(__class__=Algorithm), - data_encryption_key=MagicMock(__class__=DataKey), - encrypted_data_keys=set([]), - encryption_context={}, + algorithm=ALGORITHM, data_encryption_key=_DATA_KEY, encrypted_data_keys=set([]), encryption_context={} ) assert test.signing_key is None def test_decryption_materials_defaults(): - test = DecryptionMaterials(data_key=MagicMock(__class__=DataKey)) + test = DecryptionMaterials(data_key=_DATA_KEY) assert test.verification_key is None + assert test.algorithm is None + assert test.encryption_context is None + + +def test_decryption_materials_legacy_data_key_get(): + test = DecryptionMaterials(data_encryption_key=_DATA_KEY) + + assert test.data_encryption_key is _DATA_KEY + assert test.data_key is _DATA_KEY + + +def test_decryption_materials_legacy_data_key_set(): + test = DecryptionMaterials(data_encryption_key=_DATA_KEY) + + test.data_key = sentinel.data_key + + assert test.data_encryption_key is sentinel.data_key + assert test.data_key is sentinel.data_key diff --git a/test/unit/test_material_managers_default.py b/test/unit/test_material_managers_default.py index 9d6bd949f..6eeef525b 100644 --- a/test/unit/test_material_managers_default.py +++ b/test/unit/test_material_managers_default.py @@ -22,7 +22,7 @@ from aws_encryption_sdk.key_providers.base import MasterKeyProvider from aws_encryption_sdk.materials_managers import EncryptionMaterials from aws_encryption_sdk.materials_managers.default import DefaultCryptoMaterialsManager -from aws_encryption_sdk.structures import DataKey +from aws_encryption_sdk.structures import DataKey, EncryptedDataKey pytestmark = [pytest.mark.unit, pytest.mark.local] @@ -34,7 +34,7 @@ def patch_for_dcmm_encrypt(mocker): DefaultCryptoMaterialsManager._generate_signing_key_and_update_encryption_context.return_value = mock_signing_key mocker.patch.object(aws_encryption_sdk.materials_managers.default, "prepare_data_keys") mock_data_encryption_key = MagicMock(__class__=DataKey) - mock_encrypted_data_keys = set([mock_data_encryption_key]) + mock_encrypted_data_keys = set([MagicMock(__class__=EncryptedDataKey)]) result_pair = mock_data_encryption_key, mock_encrypted_data_keys aws_encryption_sdk.materials_managers.default.prepare_data_keys.return_value = result_pair yield result_pair, mock_signing_key @@ -128,7 +128,7 @@ def test_get_encryption_materials(patch_for_dcmm_encrypt): assert isinstance(test, EncryptionMaterials) assert test.algorithm is cmm.algorithm assert test.data_encryption_key is patch_for_dcmm_encrypt[0][0] - assert test.encrypted_data_keys is patch_for_dcmm_encrypt[0][1] + assert test.encrypted_data_keys == patch_for_dcmm_encrypt[0][1] assert test.encryption_context == encryption_context assert test.signing_key == patch_for_dcmm_encrypt[1] From 0dc48a28d77782f724479c29e22068c7a68ea4bd Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Thu, 20 Jun 2019 17:40:06 -0700 Subject: [PATCH 040/110] s/KeyRing/Keyring/g --- src/aws_encryption_sdk/identifiers.py | 2 +- .../materials_managers/__init__.py | 12 ++++++------ src/aws_encryption_sdk/structures.py | 6 +++--- test/unit/test_material_managers.py | 8 ++++---- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/aws_encryption_sdk/identifiers.py b/src/aws_encryption_sdk/identifiers.py index 0add9724d..0bec8aacd 100644 --- a/src/aws_encryption_sdk/identifiers.py +++ b/src/aws_encryption_sdk/identifiers.py @@ -330,7 +330,7 @@ class ContentAADString(Enum): NON_FRAMED_STRING_ID = b"AWSKMSEncryptionClient Single Block" -class KeyRingTraceFlag(Enum): +class KeyringTraceFlag(Enum): """KeyRing Trace actions.""" WRAPPING_KEY_GENERATED_DATA_KEY = 1 diff --git a/src/aws_encryption_sdk/materials_managers/__init__.py b/src/aws_encryption_sdk/materials_managers/__init__.py index 18ebd7898..94fd30ece 100644 --- a/src/aws_encryption_sdk/materials_managers/__init__.py +++ b/src/aws_encryption_sdk/materials_managers/__init__.py @@ -18,9 +18,9 @@ import six from attr.validators import deep_iterable, deep_mapping, instance_of, optional -from ..identifiers import Algorithm, KeyRingTraceFlag +from ..identifiers import Algorithm, KeyringTraceFlag from ..internal.utils.streams import ROStream -from ..structures import DataKey, EncryptedDataKey, KeyRingTrace +from ..structures import DataKey, EncryptedDataKey, KeyringTrace @attr.s(hash=False) @@ -64,7 +64,7 @@ class CryptographicMaterials(object): :param encrypted_data_keys: List of encrypted data keys :type encrypted_data_keys: list of :class:`EncryptedDataKey` :param keyring_trace: Any KeyRing trace entries - :type keyring_trace: list of :class:`KeyRingTrace` + :type keyring_trace: list of :class:`KeyringTrace` """ algorithm = attr.ib(validator=optional(instance_of(Algorithm))) @@ -78,7 +78,7 @@ class CryptographicMaterials(object): default=attr.Factory(list), validator=optional(deep_iterable(member_validator=instance_of(EncryptedDataKey))) ) keyring_trace = attr.ib( - default=attr.Factory(list), validator=optional(deep_iterable(member_validator=instance_of(KeyRingTrace))) + default=attr.Factory(list), validator=optional(deep_iterable(member_validator=instance_of(KeyringTrace))) ) @@ -103,7 +103,7 @@ class EncryptionMaterials(CryptographicMaterials): :param dict encryption_context: Encryption context tied to `encrypted_data_keys` :param bytes signing_key: Encoded signing key (optional) :param keyring_trace: Any KeyRing trace entries (optional) - :type keyring_trace: list of :class:`KeyRingTrace` + :type keyring_trace: list of :class:`KeyringTrace` """ signing_key = attr.ib(default=None, validator=attr.validators.optional(attr.validators.instance_of(bytes))) @@ -177,7 +177,7 @@ class DecryptionMaterials(CryptographicMaterials): :param dict encryption_context: Encryption context tied to `encrypted_data_keys` (optional) :param bytes verification_key: Raw signature verification key (optional) :param keyring_trace: Any KeyRing trace entries (optional) - :type keyring_trace: list of :class:`KeyRingTrace` + :type keyring_trace: list of :class:`KeyringTrace` """ verification_key = attr.ib(default=None, validator=attr.validators.optional(attr.validators.instance_of(bytes))) diff --git a/src/aws_encryption_sdk/structures.py b/src/aws_encryption_sdk/structures.py index 86b87b932..aed2f9163 100644 --- a/src/aws_encryption_sdk/structures.py +++ b/src/aws_encryption_sdk/structures.py @@ -108,15 +108,15 @@ class EncryptedDataKey(object): @attr.s -class KeyRingTrace(object): +class KeyringTrace(object): """Record of all actions that a KeyRing performed with a wrapping key. :param MasterKeyInfo wrapping_key: Wrapping key used :param flags: Actions performed - :type flags: set of :class:`KeyRingTraceFlag` + :type flags: set of :class:`KeyringTraceFlag` """ wrapping_key = attr.ib(validator=instance_of(MasterKeyInfo)) flags = attr.ib( - validator=deep_iterable(member_validator=instance_of(aws_encryption_sdk.identifiers.KeyRingTraceFlag)) + validator=deep_iterable(member_validator=instance_of(aws_encryption_sdk.identifiers.KeyringTraceFlag)) ) diff --git a/test/unit/test_material_managers.py b/test/unit/test_material_managers.py index 9eb32a125..fa216c8d8 100644 --- a/test/unit/test_material_managers.py +++ b/test/unit/test_material_managers.py @@ -15,7 +15,7 @@ from mock import MagicMock, sentinel from pytest_mock import mocker # noqa pylint: disable=unused-import -from aws_encryption_sdk.identifiers import KeyRingTraceFlag +from aws_encryption_sdk.identifiers import KeyringTraceFlag from aws_encryption_sdk.internal.defaults import ALGORITHM from aws_encryption_sdk.internal.utils.streams import ROStream from aws_encryption_sdk.materials_managers import ( @@ -25,7 +25,7 @@ EncryptionMaterials, EncryptionMaterialsRequest, ) -from aws_encryption_sdk.structures import DataKey, KeyRingTrace, MasterKeyInfo +from aws_encryption_sdk.structures import DataKey, KeyringTrace, MasterKeyInfo pytestmark = [pytest.mark.unit, pytest.mark.local] @@ -42,9 +42,9 @@ data_encryption_key=_DATA_KEY, encrypted_data_keys=[], keyring_trace=[ - KeyRingTrace( + KeyringTrace( wrapping_key=MasterKeyInfo(provider_id="Provider", key_info=b"Info"), - flags={KeyRingTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}, + flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}, ) ], ), From ea0b09d365ae96539b2c67c8f0193d10d99f0679 Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Wed, 26 Jun 2019 20:10:05 -0700 Subject: [PATCH 041/110] align cryptographic materials and add write-only interface --- src/aws_encryption_sdk/exceptions.py | 14 + .../materials_managers/__init__.py | 279 ++++++++++++++--- src/aws_encryption_sdk/structures.py | 130 +++++--- test/unit/test_material_managers.py | 282 ++++++++++++++++-- test/unit/test_material_managers_default.py | 19 +- .../test_streaming_client_stream_encryptor.py | 2 +- test/unit/test_structures.py | 27 ++ 7 files changed, 638 insertions(+), 115 deletions(-) diff --git a/src/aws_encryption_sdk/exceptions.py b/src/aws_encryption_sdk/exceptions.py index a71d414c0..cd60ab6bd 100644 --- a/src/aws_encryption_sdk/exceptions.py +++ b/src/aws_encryption_sdk/exceptions.py @@ -53,6 +53,13 @@ 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.""" @@ -73,6 +80,13 @@ class DecryptKeyError(AWSEncryptionSDKClientError): """Exception class for errors encountered when MasterKeys try to decrypt data keys.""" +class SignatureKeyError(AWSEncryptionSDKClientError): + """Exception class for errors encountered with signing or verification keys. + + .. versionadded:: 1.5.0 + """ + + class ActionNotAllowedError(AWSEncryptionSDKClientError): """Exception class for errors encountered when attempting to perform unallowed actions.""" diff --git a/src/aws_encryption_sdk/materials_managers/__init__.py b/src/aws_encryption_sdk/materials_managers/__init__.py index 94fd30ece..75589cc83 100644 --- a/src/aws_encryption_sdk/materials_managers/__init__.py +++ b/src/aws_encryption_sdk/materials_managers/__init__.py @@ -18,9 +18,16 @@ import six from attr.validators import deep_iterable, deep_mapping, instance_of, optional -from ..identifiers import Algorithm, KeyringTraceFlag -from ..internal.utils.streams import ROStream -from ..structures import DataKey, EncryptedDataKey, KeyringTrace +from aws_encryption_sdk.exceptions import InvalidDataKeyError, InvalidKeyringTraceError, SignatureKeyError +from aws_encryption_sdk.identifiers import Algorithm, KeyringTraceFlag +from aws_encryption_sdk.internal.utils.streams import ROStream +from aws_encryption_sdk.structures import DataKey, EncryptedDataKey, KeyringTrace, RawDataKey + +try: # Python 3.5.0 and 3.5.1 have incompatible typing modules + from typing import Iterable, Union # noqa pylint: disable=unused-import +except ImportError: # pragma: no cover + # We only actually need these imports when running the mypy checks + pass @attr.s(hash=False) @@ -41,15 +48,24 @@ class EncryptionMaterialsRequest(object): :param int plaintext_length: Length of source plaintext (optional) """ - encryption_context = attr.ib(validator=attr.validators.instance_of(dict)) - frame_length = attr.ib(validator=attr.validators.instance_of(six.integer_types)) - plaintext_rostream = attr.ib( - default=None, validator=attr.validators.optional(attr.validators.instance_of(ROStream)) - ) - algorithm = attr.ib(default=None, validator=attr.validators.optional(attr.validators.instance_of(Algorithm))) - plaintext_length = attr.ib( - default=None, validator=attr.validators.optional(attr.validators.instance_of(six.integer_types)) + encryption_context = attr.ib( + validator=deep_mapping( + key_validator=instance_of(six.string_types), value_validator=instance_of(six.string_types) + ) ) + frame_length = attr.ib(validator=instance_of(six.integer_types)) + plaintext_rostream = attr.ib(default=None, validator=optional(instance_of(ROStream))) + algorithm = attr.ib(default=None, validator=optional(instance_of(Algorithm))) + plaintext_length = attr.ib(default=None, validator=optional(instance_of(six.integer_types))) + + +def _data_key_to_raw_data_key(data_key): + # type: (Union[DataKey, RawDataKey, None]) -> Union[RawDataKey, None] + """Convert a :class:`DataKey` into a :class:`RawDataKey`.""" + if isinstance(data_key, RawDataKey) or data_key is None: + return data_key + + return RawDataKey.from_data_key(data_key=data_key) @attr.s @@ -73,13 +89,87 @@ class CryptographicMaterials(object): deep_mapping(key_validator=instance_of(six.string_types), value_validator=instance_of(six.string_types)) ) ) - data_encryption_key = attr.ib(default=None, validator=optional(instance_of(DataKey))) - encrypted_data_keys = attr.ib( - default=attr.Factory(list), validator=optional(deep_iterable(member_validator=instance_of(EncryptedDataKey))) + data_encryption_key = attr.ib( + default=None, validator=optional(instance_of(RawDataKey)), converter=_data_key_to_raw_data_key ) - keyring_trace = attr.ib( + _keyring_trace = attr.ib( default=attr.Factory(list), validator=optional(deep_iterable(member_validator=instance_of(KeyringTrace))) ) + _initialized = False + + def __attrs_post_init__(self): + """Freeze attributes after initialization.""" + self._initialized = True + + def __setattr__(self, key, value): + """Do not allow attributes to be changed once an instance is initialized.""" + if self._initialized: + raise AttributeError("can't set attribute") + + self._setattr(key, value) + + def _setattr(self, key, value): + """Special __setattr__ to avoid having to perform multi-level super calls.""" + super(CryptographicMaterials, self).__setattr__(key, value) + + def _validate_data_encryption_key(self, data_encryption_key, keyring_trace, required_flags): + # type: (Union[DataKey, RawDataKey], KeyringTrace, Iterable[KeyringTraceFlag]) -> None + """Validate that the provided data encryption key and keyring trace match for each other and the materials. + + :param RawDataKey data_encryption_key: Data encryption key + :param KeyringTrace keyring_trace: Keyring trace corresponding to data_encryption_key + :param required_flags: Iterable of required flags + :type required_flags: iterable of :class:`KeyringTraceFlag` + :raises AttributeError: if data encryption key is already set + :raises InvalidKeyringTraceError: if keyring trace does not match decrypt action + :raises InvalidKeyringTraceError: if keyring trace does not match data key provider + :raises InvalidDataKeyError: if data key length does not match algorithm suite + """ + if self.data_encryption_key is not None: + raise AttributeError("Data encryption key is already set.") + + for flag in required_flags: + if flag not in keyring_trace.flags: + raise InvalidKeyringTraceError("Keyring flags do not match action.") + + if keyring_trace.wrapping_key != data_encryption_key.key_provider: + raise InvalidKeyringTraceError("Keyring trace does not match data key provider.") + + if len(data_encryption_key.data_key) != self.algorithm.kdf_input_len: + raise InvalidDataKeyError( + "Invalid data key length {actual} must be {expected}.".format( + actual=len(data_encryption_key.data_key), expected=self.algorithm.kdf_input_len + ) + ) + + def _add_data_encryption_key(self, data_encryption_key, keyring_trace, required_flags): + # type: (Union[DataKey, RawDataKey], KeyringTrace, Iterable[KeyringTraceFlag]) -> None + """Add a plaintext data encryption key. + + :param RawDataKey data_encryption_key: Data encryption key + :param KeyringTrace keyring_trace: Trace of actions that a keyring performed + while getting this data encryption key + :raises AttributeError: if data encryption key is already set + :raises InvalidKeyringTraceError: if keyring trace does not match required actions + :raises InvalidKeyringTraceError: if keyring trace does not match data key provider + :raises InvalidDataKeyError: if data key length does not match algorithm suite + """ + self._validate_data_encryption_key( + data_encryption_key=data_encryption_key, keyring_trace=keyring_trace, required_flags=required_flags + ) + + data_key = _data_key_to_raw_data_key(data_key=data_encryption_key) + + super(CryptographicMaterials, self).__setattr__("data_encryption_key", data_key) + self._keyring_trace.append(keyring_trace) + + @property + def keyring_trace(self): + """Return a read-only version of the keyring trace. + + :rtype: tuple + """ + return tuple(self._keyring_trace) @attr.s(hash=False, init=False) @@ -106,7 +196,10 @@ class EncryptionMaterials(CryptographicMaterials): :type keyring_trace: list of :class:`KeyringTrace` """ - signing_key = attr.ib(default=None, validator=attr.validators.optional(attr.validators.instance_of(bytes))) + _encrypted_data_keys = attr.ib( + default=attr.Factory(list), validator=optional(deep_iterable(member_validator=instance_of(EncryptedDataKey))) + ) + signing_key = attr.ib(default=None, repr=False, validator=optional(instance_of(bytes))) def __init__( self, @@ -116,7 +209,7 @@ def __init__( encryption_context=None, signing_key=None, **kwargs - ): + ): # noqa we define this in the class docstring if algorithm is None: raise TypeError("algorithm must not be None") @@ -127,12 +220,79 @@ def __init__( algorithm=algorithm, encryption_context=encryption_context, data_encryption_key=data_encryption_key, - encrypted_data_keys=encrypted_data_keys, **kwargs ) - self.signing_key = signing_key + self._setattr("signing_key", signing_key) + self._setattr("_encrypted_data_keys", encrypted_data_keys) attr.validate(self) + @property + def encrypted_data_keys(self): + """Return a read-only version of the encrypted data keys. + + :rtype: frozenset + """ + return frozenset(self._encrypted_data_keys) + + def add_data_encryption_key(self, data_encryption_key, keyring_trace): + # type: (Union[DataKey, RawDataKey], KeyringTrace) -> None + """Add a plaintext data encryption key. + + .. versionadded:: 1.5.0 + + :param RawDataKey data_encryption_key: Data encryption key + :param KeyringTrace keyring_trace: Trace of actions that a keyring performed + while getting this data encryption key + :raises AttributeError: if data encryption key is already set + :raises InvalidKeyringTraceError: if keyring trace does not match generate action + :raises InvalidKeyringTraceError: if keyring trace does not match data key provider + :raises InvalidDataKeyError: if data key length does not match algorithm suite + """ + self._add_data_encryption_key( + data_encryption_key=data_encryption_key, + keyring_trace=keyring_trace, + required_flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}, + ) + + def add_encrypted_data_key(self, encrypted_data_key, keyring_trace): + # type: (EncryptedDataKey, KeyringTrace) -> None + """Add an encrypted data key with corresponding keyring trace. + + .. versionadded:: 1.5.0 + + :param EncryptedDataKey encrypted_data_key: Encrypted data key to add + :param KeyringTrace keyring_trace: Trace of actions that a keyring performed + while getting this encrypted data key + :raises InvalidKeyringTraceError: if keyring trace does not match generate action + :raises InvalidKeyringTraceError: if keyring trace does not match data key encryptor + """ + if KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY not in keyring_trace.flags: + raise InvalidKeyringTraceError("Keyring flags do not match action.") + + if keyring_trace.wrapping_key != encrypted_data_key.key_provider: + raise InvalidKeyringTraceError("Keyring trace does not match data key encryptor.") + + self._encrypted_data_keys.add(encrypted_data_key) + self._keyring_trace.append(keyring_trace) + + def add_signing_key(self, signing_key): + # type: (bytes) -> None + """Add a signing key. + + .. versionadded:: 1.5.0 + + :param bytes signing_key: Signing key + :raises AttributeError: if signing key is already set + :raises SignatureKeyError: if algorithm suite does not support signing keys + """ + if self.signing_key is not None: + raise AttributeError("Signing key is already set.") + + if self.algorithm.signing_algorithm_info is None: + raise SignatureKeyError("Algorithm suite does not support signing keys.") + + self._setattr("signing_key", signing_key) + @attr.s(hash=False) class DecryptionMaterialsRequest(object): @@ -147,9 +307,14 @@ class DecryptionMaterialsRequest(object): :param dict encryption_context: Encryption context to provide to master keys for underlying decrypt requests """ - algorithm = attr.ib(validator=attr.validators.instance_of(Algorithm)) - encrypted_data_keys = attr.ib(validator=attr.validators.instance_of(set)) - encryption_context = attr.ib(validator=attr.validators.instance_of(dict)) + algorithm = attr.ib(validator=instance_of(Algorithm)) + # TODO: Restrict this to only EncryptedDataKeys + encrypted_data_keys = attr.ib(validator=deep_iterable(member_validator=instance_of((EncryptedDataKey, DataKey)))) + encryption_context = attr.ib( + validator=deep_mapping( + key_validator=instance_of(six.string_types), value_validator=instance_of(six.string_types) + ) + ) _DEFAULT_SENTINEL = object() @@ -163,8 +328,7 @@ class DecryptionMaterials(CryptographicMaterials): .. versionadded:: 1.5.0 - The **algorithm**, **data_encryption_key**, **encrypted_data_keys**, - **encryption_context**, and **keyring_trace** parameters. + The **algorithm**, **data_encryption_key**, **encryption_context**, and **keyring_trace** parameters. .. versionadded:: 1.5.0 @@ -172,26 +336,25 @@ class DecryptionMaterials(CryptographicMaterials): :param Algorithm algorithm: Algorithm to use for encrypting message (optional) :param DataKey data_encryption_key: Plaintext data key to use for encrypting message (optional) - :param encrypted_data_keys: List of encrypted data keys (optional) - :type encrypted_data_keys: list of :class:`EncryptedDataKey` :param dict encryption_context: Encryption context tied to `encrypted_data_keys` (optional) :param bytes verification_key: Raw signature verification key (optional) :param keyring_trace: Any KeyRing trace entries (optional) :type keyring_trace: list of :class:`KeyringTrace` """ - verification_key = attr.ib(default=None, validator=attr.validators.optional(attr.validators.instance_of(bytes))) + verification_key = attr.ib(default=None, repr=False, validator=optional(instance_of(bytes))) - def __init__(self, data_key=_DEFAULT_SENTINEL, verification_key=None, **kwargs): - if any( - ( - data_key is _DEFAULT_SENTINEL and "data_encryption_key" not in kwargs, - data_key is not _DEFAULT_SENTINEL and "data_encryption_key" in kwargs, - ) - ): - raise TypeError("Exactly one of data_key or data_encryption_key must be set") + def __init__( + self, data_key=_DEFAULT_SENTINEL, verification_key=None, **kwargs + ): # noqa we define this in the class docstring - if data_key is not _DEFAULT_SENTINEL and "data_encryption_key" not in kwargs: + legacy_data_key_set = data_key is not _DEFAULT_SENTINEL + data_encryption_key_set = "data_encryption_key" in kwargs + + if legacy_data_key_set and data_encryption_key_set: + raise TypeError("Either data_key or data_encryption_key can be used but not both") + + if legacy_data_key_set and not data_encryption_key_set: kwargs["data_encryption_key"] = data_key for legacy_missing in ("algorithm", "encryption_context"): @@ -200,16 +363,46 @@ def __init__(self, data_key=_DEFAULT_SENTINEL, verification_key=None, **kwargs): super(DecryptionMaterials, self).__init__(**kwargs) - self.verification_key = verification_key + self._setattr("verification_key", verification_key) attr.validate(self) @property def data_key(self): - """Backwards-compatible shim.""" + """Backwards-compatible shim for access to data key.""" return self.data_encryption_key - @data_key.setter - def data_key(self, value): - # type: (DataKey) -> None - """Backwards-compatible shim.""" - self.data_encryption_key = value + def add_data_encryption_key(self, data_encryption_key, keyring_trace): + # type: (Union[DataKey, RawDataKey], KeyringTrace) -> None + """Add a plaintext data encryption key. + + .. versionadded:: 1.5.0 + + :param RawDataKey data_encryption_key: Data encryption key + :param KeyringTrace keyring_trace: Trace of actions that a keyring performed + while getting this data encryption key + :raises AttributeError: if data encryption key is already set + :raises InvalidKeyringTraceError: if keyring trace does not match decrypt action + :raises InvalidKeyringTraceError: if keyring trace does not match data key provider + :raises InvalidDataKeyError: if data key length does not match algorithm suite + """ + self._add_data_encryption_key( + data_encryption_key=data_encryption_key, + keyring_trace=keyring_trace, + required_flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY}, + ) + + def add_verification_key(self, verification_key): + # type: (bytes) -> None + """Add a verification key. + + .. versionadded:: 1.5.0 + + :param bytes verification_key: Verification key + """ + if self.verification_key is not None: + raise AttributeError("Verification key is already set.") + + if self.algorithm.signing_algorithm_info is None: + raise SignatureKeyError("Algorithm suite does not support signing keys.") + + self._setattr("verification_key", verification_key) diff --git a/src/aws_encryption_sdk/structures.py b/src/aws_encryption_sdk/structures.py index aed2f9163..f433f8d95 100644 --- a/src/aws_encryption_sdk/structures.py +++ b/src/aws_encryption_sdk/structures.py @@ -11,49 +11,16 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Public data structures for aws_encryption_sdk.""" +import copy + import attr import six -from attr.validators import deep_iterable, instance_of +from attr.validators import deep_iterable, deep_mapping, instance_of -import aws_encryption_sdk.identifiers +from aws_encryption_sdk.identifiers import Algorithm, ContentType, KeyringTraceFlag, ObjectType, SerializationVersion from aws_encryption_sdk.internal.str_ops import to_bytes, to_str -@attr.s(hash=True) -class MessageHeader(object): - """Deserialized message header object. - - :param version: Message format version, per spec - :type version: aws_encryption_sdk.identifiers.SerializationVersion - :param type: Message content type, per spec - :type type: aws_encryption_sdk.identifiers.ObjectType - :param algorithm: Algorithm to use for encryption - :type algorithm: aws_encryption_sdk.identifiers.Algorithm - :param bytes message_id: Message ID - :param dict encryption_context: Dictionary defining encryption context - :param encrypted_data_keys: Encrypted data keys - :type encrypted_data_keys: set of :class:`aws_encryption_sdk.structures.EncryptedDataKey` - :param content_type: Message content framing type (framed/non-framed) - :type content_type: aws_encryption_sdk.identifiers.ContentType - :param bytes content_aad_length: empty - :param int header_iv_length: Bytes in Initialization Vector value found in header - :param int frame_length: Length of message frame in bytes - """ - - version = attr.ib( - hash=True, validator=attr.validators.instance_of(aws_encryption_sdk.identifiers.SerializationVersion) - ) - type = attr.ib(hash=True, validator=attr.validators.instance_of(aws_encryption_sdk.identifiers.ObjectType)) - algorithm = attr.ib(hash=True, validator=attr.validators.instance_of(aws_encryption_sdk.identifiers.Algorithm)) - message_id = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) - encryption_context = attr.ib(hash=True, validator=attr.validators.instance_of(dict)) - encrypted_data_keys = attr.ib(hash=True, validator=attr.validators.instance_of(set)) - content_type = attr.ib(hash=True, validator=attr.validators.instance_of(aws_encryption_sdk.identifiers.ContentType)) - content_aad_length = attr.ib(hash=True, validator=attr.validators.instance_of(six.integer_types)) - header_iv_length = attr.ib(hash=True, validator=attr.validators.instance_of(six.integer_types)) - frame_length = attr.ib(hash=True, validator=attr.validators.instance_of(six.integer_types)) - - @attr.s(hash=True) class MasterKeyInfo(object): """Contains information necessary to identify a Master Key. @@ -62,8 +29,8 @@ class MasterKeyInfo(object): :param bytes key_info: MasterKey key_info value """ - provider_id = attr.ib(hash=True, validator=attr.validators.instance_of((six.string_types, bytes)), converter=to_str) - key_info = attr.ib(hash=True, validator=attr.validators.instance_of((six.string_types, bytes)), converter=to_bytes) + provider_id = attr.ib(hash=True, validator=instance_of((six.string_types, bytes)), converter=to_str) + key_info = attr.ib(hash=True, validator=instance_of((six.string_types, bytes)), converter=to_bytes) @attr.s(hash=True) @@ -75,8 +42,20 @@ class RawDataKey(object): :param bytes data_key: Plaintext data key """ - key_provider = attr.ib(hash=True, validator=attr.validators.instance_of(MasterKeyInfo)) - data_key = attr.ib(hash=True, repr=False, validator=attr.validators.instance_of(bytes)) + key_provider = attr.ib(hash=True, validator=instance_of(MasterKeyInfo)) + data_key = attr.ib(hash=True, repr=False, validator=instance_of(bytes)) + + @classmethod + def from_data_key(cls, data_key): + # type: (DataKey) -> RawDataKey + """Build an :class:`RawDataKey` from a :class:`DataKey`. + + .. versionadded:: 1.5.0 + """ + if not isinstance(data_key, DataKey): + raise TypeError("data_key must be type DataKey not {}".format(type(data_key).__name__)) + + return RawDataKey(key_provider=copy.copy(data_key.key_provider), data_key=copy.copy(data_key.data_key)) @attr.s(hash=True) @@ -89,9 +68,9 @@ class DataKey(object): :param bytes encrypted_data_key: Encrypted data key """ - key_provider = attr.ib(hash=True, validator=attr.validators.instance_of(MasterKeyInfo)) - data_key = attr.ib(hash=True, repr=False, validator=attr.validators.instance_of(bytes)) - encrypted_data_key = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) + key_provider = attr.ib(hash=True, validator=instance_of(MasterKeyInfo)) + data_key = attr.ib(hash=True, repr=False, validator=instance_of(bytes)) + encrypted_data_key = attr.ib(hash=True, validator=instance_of(bytes)) @attr.s(hash=True) @@ -103,20 +82,75 @@ class EncryptedDataKey(object): :param bytes encrypted_data_key: Encrypted data key """ - key_provider = attr.ib(hash=True, validator=attr.validators.instance_of(MasterKeyInfo)) - encrypted_data_key = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) + key_provider = attr.ib(hash=True, validator=instance_of(MasterKeyInfo)) + encrypted_data_key = attr.ib(hash=True, validator=instance_of(bytes)) + + @classmethod + def from_data_key(cls, data_key): + # type: (DataKey) -> EncryptedDataKey + """Build an :class:`EncryptedDataKey` from a :class:`DataKey`. + + .. versionadded:: 1.5.0 + """ + if not isinstance(data_key, DataKey): + raise TypeError("data_key must be type DataKey not {}".format(type(data_key).__name__)) + + return EncryptedDataKey( + key_provider=copy.copy(data_key.key_provider), encrypted_data_key=copy.copy(data_key.encrypted_data_key) + ) @attr.s class KeyringTrace(object): """Record of all actions that a KeyRing performed with a wrapping key. + .. versionadded:: 1.5.0 + :param MasterKeyInfo wrapping_key: Wrapping key used :param flags: Actions performed :type flags: set of :class:`KeyringTraceFlag` """ wrapping_key = attr.ib(validator=instance_of(MasterKeyInfo)) - flags = attr.ib( - validator=deep_iterable(member_validator=instance_of(aws_encryption_sdk.identifiers.KeyringTraceFlag)) + flags = attr.ib(validator=deep_iterable(member_validator=instance_of(KeyringTraceFlag))) + + +@attr.s(hash=True) +class MessageHeader(object): + """Deserialized message header object. + + :param version: Message format version, per spec + :type version: SerializationVersion + :param type: Message content type, per spec + :type type: ObjectType + :param algorithm: Algorithm to use for encryption + :type algorithm: Algorithm + :param bytes message_id: Message ID + :param dict encryption_context: Dictionary defining encryption context + :param encrypted_data_keys: Encrypted data keys + :type encrypted_data_keys: set of :class:`aws_encryption_sdk.structures.EncryptedDataKey` + :param content_type: Message content framing type (framed/non-framed) + :type content_type: ContentType + :param bytes content_aad_length: empty + :param int header_iv_length: Bytes in Initialization Vector value found in header + :param int frame_length: Length of message frame in bytes + """ + + version = attr.ib(hash=True, validator=instance_of(SerializationVersion)) + type = attr.ib(hash=True, validator=instance_of(ObjectType)) + algorithm = attr.ib(hash=True, validator=instance_of(Algorithm)) + message_id = attr.ib(hash=True, validator=instance_of(bytes)) + encryption_context = attr.ib( + hash=True, + validator=deep_mapping( + key_validator=instance_of(six.string_types), value_validator=instance_of(six.string_types) + ), + ) + # TODO: Restrict this to only EncryptedDataKeys + encrypted_data_keys = attr.ib( + hash=True, validator=deep_iterable(member_validator=instance_of((EncryptedDataKey, DataKey))) ) + content_type = attr.ib(hash=True, validator=instance_of(ContentType)) + content_aad_length = attr.ib(hash=True, validator=instance_of(six.integer_types)) + header_iv_length = attr.ib(hash=True, validator=instance_of(six.integer_types)) + frame_length = attr.ib(hash=True, validator=instance_of(six.integer_types)) diff --git a/test/unit/test_material_managers.py b/test/unit/test_material_managers.py index fa216c8d8..a1816fe10 100644 --- a/test/unit/test_material_managers.py +++ b/test/unit/test_material_managers.py @@ -12,10 +12,11 @@ # language governing permissions and limitations under the License. """Test suite for aws_encryption_sdk.materials_managers""" import pytest -from mock import MagicMock, sentinel +from mock import MagicMock from pytest_mock import mocker # noqa pylint: disable=unused-import -from aws_encryption_sdk.identifiers import KeyringTraceFlag +from aws_encryption_sdk.exceptions import InvalidDataKeyError, InvalidKeyringTraceError, SignatureKeyError +from aws_encryption_sdk.identifiers import AlgorithmSuite, KeyringTraceFlag from aws_encryption_sdk.internal.defaults import ALGORITHM from aws_encryption_sdk.internal.utils.streams import ROStream from aws_encryption_sdk.materials_managers import ( @@ -24,8 +25,9 @@ DecryptionMaterialsRequest, EncryptionMaterials, EncryptionMaterialsRequest, + _data_key_to_raw_data_key, ) -from aws_encryption_sdk.structures import DataKey, KeyringTrace, MasterKeyInfo +from aws_encryption_sdk.structures import DataKey, EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey pytestmark = [pytest.mark.unit, pytest.mark.local] @@ -34,13 +36,14 @@ data_key=b"1234567890123456789012", encrypted_data_key=b"asdf", ) +_RAW_DATA_KEY = RawDataKey.from_data_key(_DATA_KEY) +_ENCRYPTED_DATA_KEY = EncryptedDataKey.from_data_key(_DATA_KEY) _VALID_KWARGS = { "CryptographicMaterials": dict( algorithm=ALGORITHM, encryption_context={"additional": "data"}, data_encryption_key=_DATA_KEY, - encrypted_data_keys=[], keyring_trace=[ KeyringTrace( wrapping_key=MasterKeyInfo(provider_id="Provider", key_info=b"Info"), @@ -70,6 +73,15 @@ _REMOVE = object() +def _copy_and_update_kwargs(class_name, mod_kwargs): + kwargs = _VALID_KWARGS[class_name].copy() + kwargs.update(mod_kwargs) + purge_keys = [key for key, val in kwargs.items() if val is _REMOVE] + for key in purge_keys: + del kwargs[key] + return kwargs + + @pytest.mark.parametrize( "attr_class, invalid_kwargs", ( @@ -90,19 +102,30 @@ (DecryptionMaterialsRequest, dict(encryption_context=None)), (DecryptionMaterials, dict(verification_key=5555)), (DecryptionMaterials, dict(data_key=_DATA_KEY, data_encryption_key=_DATA_KEY)), - (DecryptionMaterials, dict(data_key=_REMOVE, data_encryption_key=_REMOVE)), ), ) def test_attributes_fails(attr_class, invalid_kwargs): - kwargs = _VALID_KWARGS[attr_class.__name__].copy() - kwargs.update(invalid_kwargs) - purge_keys = [key for key, val in kwargs.items() if val is _REMOVE] - for key in purge_keys: - del kwargs[key] + kwargs = _copy_and_update_kwargs(attr_class.__name__, invalid_kwargs) with pytest.raises(TypeError): attr_class(**kwargs) +@pytest.mark.parametrize( + "attr_class, kwargs_modification", + ( + (CryptographicMaterials, {}), + (EncryptionMaterials, {}), + (DecryptionMaterials, {}), + (DecryptionMaterials, dict(data_key=_REMOVE, data_encryption_key=_REMOVE)), + (DecryptionMaterials, dict(data_key=_REMOVE, data_encryption_key=_RAW_DATA_KEY)), + (DecryptionMaterials, dict(data_key=_RAW_DATA_KEY, data_encryption_key=_REMOVE)), + ), +) +def test_attributes_good(attr_class, kwargs_modification): + kwargs = _copy_and_update_kwargs(attr_class.__name__, kwargs_modification) + attr_class(**kwargs) + + def test_encryption_materials_request_attributes_defaults(): test = EncryptionMaterialsRequest(encryption_context={}, frame_length=5) assert test.plaintext_rostream is None @@ -127,14 +150,239 @@ def test_decryption_materials_defaults(): def test_decryption_materials_legacy_data_key_get(): test = DecryptionMaterials(data_encryption_key=_DATA_KEY) - assert test.data_encryption_key is _DATA_KEY - assert test.data_key is _DATA_KEY + assert test.data_encryption_key == _RAW_DATA_KEY + assert test.data_key == _RAW_DATA_KEY -def test_decryption_materials_legacy_data_key_set(): - test = DecryptionMaterials(data_encryption_key=_DATA_KEY) +@pytest.mark.parametrize( + "data_key, expected", ((_DATA_KEY, _RAW_DATA_KEY), (_RAW_DATA_KEY, _RAW_DATA_KEY), (None, None)) +) +def test_data_key_to_raw_data_key_success(data_key, expected): + test = _data_key_to_raw_data_key(data_key=data_key) + + assert test == expected + + +def test_data_key_to_raw_data_key_fail(): + with pytest.raises(TypeError) as excinfo: + _data_key_to_raw_data_key(data_key="not a data key") + + excinfo.match("data_key must be type DataKey not str") + + +def _cryptographic_materials_attributes(): + for material in (CryptographicMaterials, EncryptionMaterials, DecryptionMaterials): + for attribute in ( + "algorithm", + "encryption_context", + "data_encryption_key", + "_keyring_trace", + "keyring_trace", + "_initialized", + ): + yield material, attribute + + for attribute in ("_encrypted_data_keys", "encrypted_data_keys", "signing_key"): + yield EncryptionMaterials, attribute + + for attribute in ("data_key", "verification_key"): + yield DecryptionMaterials, attribute + + +@pytest.mark.parametrize("material_class, attribute_name", _cryptographic_materials_attributes()) +def test_cryptographic_materials_cannot_change_attribute(material_class, attribute_name): + test = material_class(algorithm=ALGORITHM, encryption_context={}) + + with pytest.raises(AttributeError) as excinfo: + setattr(test, attribute_name, 42) + + excinfo.match("can't set attribute") + + +@pytest.mark.parametrize("material_class", (CryptographicMaterials, EncryptionMaterials, DecryptionMaterials)) +def test_immutable_keyring_trace(material_class): + materials = material_class(**_VALID_KWARGS[material_class.__name__]) + + with pytest.raises(AttributeError): + materials.keyring_trace.append(42) + + +def test_immutable_encrypted_data_keys(): + materials = EncryptionMaterials(**_VALID_KWARGS["EncryptionMaterials"]) + + with pytest.raises(AttributeError): + materials.encrypted_data_keys.add(42) + + +@pytest.mark.parametrize( + "material_class, flag", + ( + (EncryptionMaterials, KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY), + (DecryptionMaterials, KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY), + ), +) +def test_add_data_encryption_key_success(material_class, flag): + kwargs = _copy_and_update_kwargs(material_class.__name__, dict(data_encryption_key=_REMOVE, data_key=_REMOVE)) + materials = material_class(**kwargs) + + materials.add_data_encryption_key( + data_encryption_key=RawDataKey( + key_provider=MasterKeyInfo(provider_id="a", key_info=b"b"), data_key=b"1" * ALGORITHM.kdf_input_len + ), + keyring_trace=KeyringTrace(wrapping_key=MasterKeyInfo(provider_id="a", key_info=b"b"), flags={flag}), + ) + + +def _add_data_encryption_key_test_cases(): + for material_class, required_flags in ( + (EncryptionMaterials, KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY), + (DecryptionMaterials, KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY), + ): + yield ( + material_class, + dict(data_encryption_key=_RAW_DATA_KEY, data_key=_REMOVE), + _RAW_DATA_KEY, + KeyringTrace(wrapping_key=_RAW_DATA_KEY.key_provider, flags={required_flags}), + AttributeError, + "Data encryption key is already set.", + ) + yield ( + material_class, + dict(data_encryption_key=_REMOVE, data_key=_REMOVE), + _RAW_DATA_KEY, + KeyringTrace(wrapping_key=_RAW_DATA_KEY.key_provider, flags=set()), + InvalidKeyringTraceError, + "Keyring flags do not match action.", + ) + yield ( + material_class, + dict(data_encryption_key=_REMOVE, data_key=_REMOVE), + RawDataKey(key_provider=MasterKeyInfo(provider_id="a", key_info=b"b"), data_key=b"asdf"), + KeyringTrace(wrapping_key=MasterKeyInfo(provider_id="c", key_info=b"d"), flags={required_flags}), + InvalidKeyringTraceError, + "Keyring trace does not match data key provider.", + ) + yield ( + material_class, + dict(data_encryption_key=_REMOVE, data_key=_REMOVE), + RawDataKey(key_provider=_RAW_DATA_KEY.key_provider, data_key=b"1234"), + KeyringTrace(wrapping_key=_RAW_DATA_KEY.key_provider, flags={required_flags}), + InvalidDataKeyError, + r"Invalid data key length *", + ) + + +@pytest.mark.parametrize( + "material_class, mod_kwargs, data_encryption_key, keyring_trace, exception_type, exception_message", + _add_data_encryption_key_test_cases(), +) +def test_add_data_encryption_key_fail( + material_class, mod_kwargs, data_encryption_key, keyring_trace, exception_type, exception_message +): + kwargs = _copy_and_update_kwargs(material_class.__name__, mod_kwargs) + materials = material_class(**kwargs) + + with pytest.raises(exception_type) as excinfo: + materials.add_data_encryption_key(data_encryption_key=data_encryption_key, keyring_trace=keyring_trace) + + excinfo.match(exception_message) + + +def test_add_encrypted_data_key_success(): + kwargs = _copy_and_update_kwargs("EncryptionMaterials", {}) + materials = EncryptionMaterials(**kwargs) + + materials.add_encrypted_data_key( + _ENCRYPTED_DATA_KEY, + keyring_trace=KeyringTrace( + wrapping_key=_ENCRYPTED_DATA_KEY.key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY} + ), + ) + + +@pytest.mark.parametrize( + "encrypted_data_key, keyring_trace, exception_type, exception_message", + ( + ( + _ENCRYPTED_DATA_KEY, + KeyringTrace(wrapping_key=_ENCRYPTED_DATA_KEY.key_provider, flags=set()), + InvalidKeyringTraceError, + "Keyring flags do not match action.", + ), + ( + EncryptedDataKey(key_provider=MasterKeyInfo(provider_id="a", key_info=b"b"), encrypted_data_key=b"asdf"), + KeyringTrace( + wrapping_key=MasterKeyInfo(provider_id="not a match", key_info=b"really not a match"), + flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}, + ), + InvalidKeyringTraceError, + "Keyring trace does not match data key encryptor.", + ), + ), +) +def test_add_encrypted_data_key_fail(encrypted_data_key, keyring_trace, exception_type, exception_message): + kwargs = _copy_and_update_kwargs("EncryptionMaterials", {}) + materials = EncryptionMaterials(**kwargs) + + with pytest.raises(exception_type) as excinfo: + materials.add_encrypted_data_key(encrypted_data_key=encrypted_data_key, keyring_trace=keyring_trace) + + excinfo.match(exception_message) + + +def test_add_signing_key_success(): + kwargs = _copy_and_update_kwargs("EncryptionMaterials", dict(signing_key=_REMOVE)) + materials = EncryptionMaterials(**kwargs) + + materials.add_signing_key(signing_key=b"") + + +@pytest.mark.parametrize( + "mod_kwargs, signing_key, exception_type, exception_message", + ( + ({}, b"", AttributeError, "Signing key is already set."), + ( + dict(signing_key=_REMOVE, algorithm=AlgorithmSuite.AES_256_GCM_IV12_TAG16), + b"", + SignatureKeyError, + "Algorithm suite does not support signing keys.", + ), + ), +) +def test_add_signing_key_fail(mod_kwargs, signing_key, exception_type, exception_message): + kwargs = _copy_and_update_kwargs("EncryptionMaterials", mod_kwargs) + materials = EncryptionMaterials(**kwargs) + + with pytest.raises(exception_type) as excinfo: + materials.add_signing_key(signing_key=signing_key) + + excinfo.match(exception_message) + + +def test_add_verification_key_success(): + kwargs = _copy_and_update_kwargs("DecryptionMaterials", dict(verification_key=_REMOVE)) + materials = DecryptionMaterials(**kwargs) + + materials.add_verification_key(verification_key=b"") + + +@pytest.mark.parametrize( + "mod_kwargs, verification_key, exception_type, exception_message", + ( + ({}, b"", AttributeError, "Verification key is already set."), + ( + dict(verification_key=_REMOVE, algorithm=AlgorithmSuite.AES_256_GCM_IV12_TAG16), + b"", + SignatureKeyError, + "Algorithm suite does not support signing keys.", + ), + ), +) +def test_add_verification_key_fail(mod_kwargs, verification_key, exception_type, exception_message): + kwargs = _copy_and_update_kwargs("DecryptionMaterials", mod_kwargs) + materials = DecryptionMaterials(**kwargs) - test.data_key = sentinel.data_key + with pytest.raises(exception_type) as excinfo: + materials.add_verification_key(verification_key=verification_key) - assert test.data_encryption_key is sentinel.data_key - assert test.data_key is sentinel.data_key + excinfo.match(exception_message) diff --git a/test/unit/test_material_managers_default.py b/test/unit/test_material_managers_default.py index 6eeef525b..20aaa8dd6 100644 --- a/test/unit/test_material_managers_default.py +++ b/test/unit/test_material_managers_default.py @@ -22,10 +22,17 @@ from aws_encryption_sdk.key_providers.base import MasterKeyProvider from aws_encryption_sdk.materials_managers import EncryptionMaterials from aws_encryption_sdk.materials_managers.default import DefaultCryptoMaterialsManager -from aws_encryption_sdk.structures import DataKey, EncryptedDataKey +from aws_encryption_sdk.structures import DataKey, EncryptedDataKey, MasterKeyInfo, RawDataKey pytestmark = [pytest.mark.unit, pytest.mark.local] +_DATA_KEY = DataKey( + key_provider=MasterKeyInfo(provider_id="Provider", key_info=b"Info"), + data_key=b"1234567890123456789012", + encrypted_data_key=b"asdf", +) +_ENCRYPTED_DATA_KEY = EncryptedDataKey.from_data_key(_DATA_KEY) + @pytest.fixture def patch_for_dcmm_encrypt(mocker): @@ -33,8 +40,8 @@ def patch_for_dcmm_encrypt(mocker): mock_signing_key = b"ex_signing_key" DefaultCryptoMaterialsManager._generate_signing_key_and_update_encryption_context.return_value = mock_signing_key mocker.patch.object(aws_encryption_sdk.materials_managers.default, "prepare_data_keys") - mock_data_encryption_key = MagicMock(__class__=DataKey) - mock_encrypted_data_keys = set([MagicMock(__class__=EncryptedDataKey)]) + mock_data_encryption_key = _DATA_KEY + mock_encrypted_data_keys = set([_ENCRYPTED_DATA_KEY]) result_pair = mock_data_encryption_key, mock_encrypted_data_keys aws_encryption_sdk.materials_managers.default.prepare_data_keys.return_value = result_pair yield result_pair, mock_signing_key @@ -50,7 +57,7 @@ def patch_for_dcmm_decrypt(mocker): def build_cmm(): mock_mkp = MagicMock(__class__=MasterKeyProvider) - mock_mkp.decrypt_data_key_from_list.return_value = MagicMock(__class__=DataKey) + mock_mkp.decrypt_data_key_from_list.return_value = _DATA_KEY mock_mkp.master_keys_for_encryption.return_value = ( sentinel.primary_mk, set([sentinel.primary_mk, sentinel.mk_a, sentinel.mk_b]), @@ -127,7 +134,7 @@ def test_get_encryption_materials(patch_for_dcmm_encrypt): ) assert isinstance(test, EncryptionMaterials) assert test.algorithm is cmm.algorithm - assert test.data_encryption_key is patch_for_dcmm_encrypt[0][0] + assert test.data_encryption_key == RawDataKey.from_data_key(patch_for_dcmm_encrypt[0][0]) assert test.encrypted_data_keys == patch_for_dcmm_encrypt[0][1] assert test.encryption_context == encryption_context assert test.signing_key == patch_for_dcmm_encrypt[1] @@ -232,5 +239,5 @@ def test_decrypt_materials(mocker, patch_for_dcmm_decrypt): cmm._load_verification_key_from_encryption_context.assert_called_once_with( algorithm=mock_request.algorithm, encryption_context=mock_request.encryption_context ) - assert test.data_key is cmm.master_key_provider.decrypt_data_key_from_list.return_value + assert test.data_key == RawDataKey.from_data_key(cmm.master_key_provider.decrypt_data_key_from_list.return_value) assert test.verification_key == patch_for_dcmm_decrypt diff --git a/test/unit/test_streaming_client_stream_encryptor.py b/test/unit/test_streaming_client_stream_encryptor.py index 501214e9f..5cb2b8e37 100644 --- a/test/unit/test_streaming_client_stream_encryptor.py +++ b/test/unit/test_streaming_client_stream_encryptor.py @@ -247,7 +247,7 @@ def test_prep_message_framed_message( encryption_context=VALUES["encryption_context"], ) test_encryptor.content_type = ContentType.FRAMED_DATA - test_encryption_context = {aws_encryption_sdk.internal.defaults.ENCODED_SIGNER_KEY: sentinel.decoded_bytes} + test_encryption_context = {aws_encryption_sdk.internal.defaults.ENCODED_SIGNER_KEY: "DECODED_BYTES"} self.mock_encryption_materials.encryption_context = test_encryption_context self.mock_encryption_materials.encrypted_data_keys = self.mock_encrypted_data_keys diff --git a/test/unit/test_structures.py b/test/unit/test_structures.py index 1a9caa01d..efce6fadc 100644 --- a/test/unit/test_structures.py +++ b/test/unit/test_structures.py @@ -107,3 +107,30 @@ def test_data_key_repr_str(cls, params): assert data_key_check not in str(test) assert data_key_check not in repr(test) + + +@pytest.fixture +def ex_data_key(): + return DataKey(**VALID_KWARGS[DataKey][0]) + + +def test_encrypted_data_key_from_data_key_success(ex_data_key): + test = EncryptedDataKey.from_data_key(ex_data_key) + + assert test.key_provider == ex_data_key.key_provider + assert test.encrypted_data_key == ex_data_key.encrypted_data_key + + +def test_raw_data_key_from_data_key_success(ex_data_key): + test = RawDataKey.from_data_key(ex_data_key) + + assert test.key_provider == ex_data_key.key_provider + assert test.data_key == ex_data_key.data_key + + +@pytest.mark.parametrize("data_key_class", (EncryptedDataKey, RawDataKey)) +def test_raw_and_encrypted_data_key_from_data_key_fail(data_key_class): + with pytest.raises(TypeError) as excinfo: + data_key_class.from_data_key(b"ahjseofij") + + excinfo.match(r"data_key must be type DataKey not bytes") From 9b3d4e2f9074fc837bd69e30ad106ca70cbbf366 Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Wed, 26 Jun 2019 20:15:11 -0700 Subject: [PATCH 042/110] encrypted_data_keys must only contain EncryptedDataKey --- src/aws_encryption_sdk/materials_managers/__init__.py | 3 +-- src/aws_encryption_sdk/structures.py | 5 +---- test/unit/test_caches.py | 8 +++----- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/aws_encryption_sdk/materials_managers/__init__.py b/src/aws_encryption_sdk/materials_managers/__init__.py index 75589cc83..4ed77e315 100644 --- a/src/aws_encryption_sdk/materials_managers/__init__.py +++ b/src/aws_encryption_sdk/materials_managers/__init__.py @@ -308,8 +308,7 @@ class DecryptionMaterialsRequest(object): """ algorithm = attr.ib(validator=instance_of(Algorithm)) - # TODO: Restrict this to only EncryptedDataKeys - encrypted_data_keys = attr.ib(validator=deep_iterable(member_validator=instance_of((EncryptedDataKey, DataKey)))) + encrypted_data_keys = attr.ib(validator=deep_iterable(member_validator=instance_of(EncryptedDataKey))) encryption_context = attr.ib( validator=deep_mapping( key_validator=instance_of(six.string_types), value_validator=instance_of(six.string_types) diff --git a/src/aws_encryption_sdk/structures.py b/src/aws_encryption_sdk/structures.py index f433f8d95..635f661ce 100644 --- a/src/aws_encryption_sdk/structures.py +++ b/src/aws_encryption_sdk/structures.py @@ -146,10 +146,7 @@ class MessageHeader(object): key_validator=instance_of(six.string_types), value_validator=instance_of(six.string_types) ), ) - # TODO: Restrict this to only EncryptedDataKeys - encrypted_data_keys = attr.ib( - hash=True, validator=deep_iterable(member_validator=instance_of((EncryptedDataKey, DataKey))) - ) + encrypted_data_keys = attr.ib(hash=True, validator=deep_iterable(member_validator=instance_of(EncryptedDataKey))) content_type = attr.ib(hash=True, validator=instance_of(ContentType)) content_aad_length = attr.ib(hash=True, validator=instance_of(six.integer_types)) header_iv_length = attr.ib(hash=True, validator=instance_of(six.integer_types)) diff --git a/test/unit/test_caches.py b/test/unit/test_caches.py index 250ad6d5b..58c1b4944 100644 --- a/test/unit/test_caches.py +++ b/test/unit/test_caches.py @@ -27,7 +27,7 @@ ) from aws_encryption_sdk.identifiers import Algorithm from aws_encryption_sdk.materials_managers import DecryptionMaterialsRequest, EncryptionMaterialsRequest -from aws_encryption_sdk.structures import DataKey, MasterKeyInfo +from aws_encryption_sdk.structures import EncryptedDataKey, MasterKeyInfo pytestmark = [pytest.mark.unit, pytest.mark.local] @@ -47,19 +47,17 @@ }, "encrypted_data_keys": [ { - "key": DataKey( + "key": EncryptedDataKey( key_provider=MasterKeyInfo(provider_id="this is a provider ID", key_info=b"this is some key info"), - data_key=b"super secret key!", encrypted_data_key=b"super secret key, now with encryption!", ), "hash": b"TYoFeYuxns/FBlaw4dsRDOv25OCEKuZG9iXt5iEdJ8LU7n5glgkDAVxWUEYC4JKKykJdHkaVpxcDvNqS6UswiQ==", }, { - "key": DataKey( + "key": EncryptedDataKey( key_provider=MasterKeyInfo( provider_id="another provider ID!", key_info=b"this is some different key info" ), - data_key=b"better super secret key!", encrypted_data_key=b"better super secret key, now with encryption!", ), "hash": b"wSrDlPM2ocIj9MAtD94ULSR0Qrt1muBovBDRL+DsSTNphJEM3CZ/h3OyvYL8BR2EIXx0m7GYwv8dGtyZL2D87w==", From ac67a6faefe891256a59d28493a35a05cec8ebbd Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Wed, 26 Jun 2019 20:28:02 -0700 Subject: [PATCH 043/110] fix test to be Python 2 compatible --- test/unit/test_structures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/test_structures.py b/test/unit/test_structures.py index efce6fadc..e1070c574 100644 --- a/test/unit/test_structures.py +++ b/test/unit/test_structures.py @@ -133,4 +133,4 @@ def test_raw_and_encrypted_data_key_from_data_key_fail(data_key_class): with pytest.raises(TypeError) as excinfo: data_key_class.from_data_key(b"ahjseofij") - excinfo.match(r"data_key must be type DataKey not bytes") + excinfo.match(r"data_key must be type DataKey not *") From 0921eff1813133c85c7f1c0a9c65d9492c8a32d9 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 27 Jun 2019 16:41:21 -0700 Subject: [PATCH 044/110] Changes in raw keyrings according to new keyring materials --- src/aws_encryption_sdk/keyring/raw_keyring.py | 240 ++++++++++-------- 1 file changed, 135 insertions(+), 105 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 74e19c653..71321e08d 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -13,6 +13,7 @@ """Resources required for Raw Keyrings.""" import os import struct +import six import attr @@ -23,27 +24,108 @@ from aws_encryption_sdk.internal.str_ops import to_bytes from aws_encryption_sdk.keyring.base import Keyring from aws_encryption_sdk.structures import DataKey, MasterKeyInfo, RawDataKey +from aws_encryption_sdk.exceptions import EncryptKeyError -@attr.s -class RawAESKeyring(Keyring): - """Public class for Raw AES Keyring.""" +def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping_algorithm, key_name): + # Check if data key already exists + if not encryption_materials.data_encryption_key: - key_namespace = attr.ib(validator=attr.validators.instance_of(str)) - key_name = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) - wrapping_key = attr.ib(hash=True, validator=attr.validators.instance_of(WrappingKey)) - wrapping_algorithm = attr.ib(validator=attr.validators.instance_of(WrappingAlgorithm)) + # Generate data key + plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) - key_provider = MasterKeyInfo(provider_id=key_namespace, key_info=key_name) + # Check if data key is generated + if not plaintext_data_key: + return EncryptKeyError("Unable to generate data encryption key.") - key_info_prefix = struct.pack( - ">{}sII".format(len(key_name)), - to_bytes(key_name), - # Tag Length is stored in bits, not bytes - wrapping_algorithm.algorithm.tag_len * 8, - wrapping_algorithm.algorithm.iv_len, + # plaintext_data_key to RawDataKey + data_encryption_key = RawDataKey( + key_provider=key_provider, data_key=plaintext_data_key + ) + + # Add generated data key to encryption_materials + encryption_materials.add_data_encryption_key(data_encryption_key, encryption_materials.keyring_trace) + + else: + plaintext_data_key = encryption_materials.data_encryption_key + + # Encrypt data key + encrypted_wrapped_key = wrapping_key.encrypt( + plaintext_data_key=plaintext_data_key, encryption_context=encryption_materials.encryption_context ) + # EncryptedData to EncryptedDataKey + encrypted_data_key = aws_encryption_sdk.internal.formatting.serialize.serialize_wrapped_key( + key_provider=key_provider, + wrapping_algorithm=wrapping_algorithm, + wrapping_key_id=key_name, + encrypted_wrapped_key=encrypted_wrapped_key + ) + + # Add encrypted data key to encryption_materials + encryption_materials.add_encrypted_data_key(encrypted_data_key, encryption_materials.keyring_trace) + + return encryption_materials + + +def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, key_name, encrypted_data_key): + # Check if plaintext data key exists + if decryption_materials.data_key: + return decryption_materials + + # Wrapped EncryptedDataKey to deserialized EncryptedData + encrypted_wrapped_key = aws_encryption_sdk.internal.formatting.deserialize.deserialize_wrapped_key( + wrapping_algorithm=wrapping_algorithm, + wrapping_key_id=key_name, + wrapped_encrypted_key=encrypted_data_key + ) + + # EncryptedData to raw key string + plaintext_data_key = wrapping_key.decrypt( + encrypted_wrapped_data_key=encrypted_wrapped_key, + encryption_context=decryption_materials.encryption_context + ) + + # Update decryption materials + data_encryption_key = DataKey( + key_provider=encrypted_data_key.key_provider, + data_key=plaintext_data_key, + encrypted_data_key=encrypted_data_key.encrypted_data_key + ) + decryption_materials.add_data_encryption_key(data_encryption_key, decryption_materials.keyring_trace) + + return decryption_materials + + +@attr.s +class RawAESKeyring(Keyring): + """Public class for Raw AES Keyring. + + :param str key_namespace: String defining the keyring ID + :param bytes key_name: Key ID + :param wrapping_key: Encryption key with which to wrap plaintext data key + :type wrapping_key: WrappingKey + :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key + :type wrapping_algorithm: WrappingAlgorithm + """ + + key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) + key_name = attr.ib(hash=True, validator=attr.validators.instance_of(six.binary_type)) + _wrapping_key = attr.ib(hash=True, repr=False, validator=attr.validators.instance_of(WrappingKey)) + _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) + + def __attrs_post_init__(self): + + _key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name) + + _key_info_prefix = struct.pack( + ">{}sII".format(len(self.key_name)), + to_bytes(self.key_name), + # Tag Length is stored in bits, not bytes + self._wrapping_algorithm.algorithm.tag_len * 8, + self._wrapping_algorithm.algorithm.iv_len + ) + def on_encrypt(self, encryption_materials): """Generate a data key if not present and encrypt it using any available wrapping key. @@ -55,76 +137,54 @@ def on_encrypt(self, encryption_materials): :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - # Generate data key - plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) - - # Encrypt data key - encrypted_wrapped_key = self.wrapping_key.encrypt( - plaintext_data_key=plaintext_data_key, encryption_context=encryption_materials.encryption_context - ) - - encrypted_data_key = aws_encryption_sdk.internal.formatting.serialize.serialize_wrapped_key( - key_provider=self.key_provider, - wrapping_algorithm=self.wrapping_algorithm, - wrapping_key_id=self.key_name, - encrypted_wrapped_key=encrypted_wrapped_key, - ) - - # Update keyring trace - - # Update encryption materials - encryption_materials.data_encryption_key = RawDataKey( - key_provider=self.key_provider, data_key=plaintext_data_key - ) - encryption_materials.encrypted_data_keys.add(encrypted_data_key) + encryption_materials = on_encrypt_helper(encryption_materials, self._key_provider, self._wrapping_key, + self._wrapping_algorithm, self.key_name) return encryption_materials - def on_decrypt(self, decryption_materials): + def on_decrypt(self, decryption_materials, encrypted_data_keys): """Attempt to decrypt the encrypted data keys. - :param decryption_materials: Contains verification key, list of encrypted data keys. + :param decryption_materials: Contains verification key, algorithm, encryption context and keyring trace. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials - :returns: Contains verification key, list of encrypted data keys and decrypted data key. + :param encrypted_data_keys: List of encrypted data keys. + :type: List of `aws_encryption_sdk.structures.EncryptedDataKey` + :returns: Contains verification key, algorithm, data_encryption_key, encryption context and keyring trac :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials """ # Decrypt data key - expected_key_info_len = len(self.key_info_prefix) + self.wrapping_algorithm.algorithm.iv_len + expected_key_info_len = len(self._key_info_prefix) + self._wrapping_algorithm.algorithm.iv_len if ( - decryption_materials.encrypted_data_key.key_provider.provider_id == self.key_provider.provider_id - and len(decryption_materials.encrypted_data_key.key_provider.key_info) == expected_key_info_len - and decryption_materials.encrypted_data_key.key_provider.key_info.startswith(self.key_info_prefix) + encrypted_data_keys.key_provider.provider_id == self._key_provider.provider_id + and len(encrypted_data_keys.key_provider.key_info) == expected_key_info_len + and encrypted_data_keys.key_provider.key_info.startswith(self._key_info_prefix) ): - encrypted_wrapped_key = aws_encryption_sdk.internal.formatting.deserialize.deserialize_wrapped_key( - wrapping_algorithm=self.wrapping_algorithm, - wrapping_key_id=self.key_name, - wrapped_encrypted_key=decryption_materials.encrypted_data_key, - ) - plaintext_data_key = self.wrapping_key.decrypt( - encrypted_wrapped_data_key=encrypted_wrapped_key, - encryption_context=decryption_materials.encryption_context, - ) - decryption_materials.data_key = DataKey( - key_provider=decryption_materials.encrypted_data_key.key_provider, - data_key=plaintext_data_key, - encrypted_data_key=decryption_materials.encrypted_data_key.encrypted_data_key, - ) - - # Update keyring trace + decryption_materials = on_decrypt_helper(decryption_materials, self._wrapping_key, self._wrapping_algorithm, + self.key_name, encrypted_data_keys) return decryption_materials class RawRSAKeyring(Keyring): - """Public class for Raw RSA Keyring.""" + """Public class for Raw RSA Keyring. + + :param str key_namespace: String defining the keyring ID + :param bytes key_name: Key ID + :param wrapping_key: Encryption key with which to wrap plaintext data key + :type wrapping_key: WrappingKey + :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key + :type wrapping_algorithm: WrappingAlgorithm + :param key_provider: Complete information about the key in the keyring + :type key_provider: MasterKeyInfo + """ key_namespace = attr.ib(validator=attr.validators.instance_of(str)) key_name = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) - wrapping_key = attr.ib(hash=True, validator=attr.validators.instance_of(WrappingKey)) - wrapping_algorithm = attr.ib(validator=attr.validators.instance_of(WrappingAlgorithm)) + _wrapping_key = attr.ib(hash=True, repr=False, validator=attr.validators.instance_of(WrappingKey)) + _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) - key_provider = MasterKeyInfo(provider_id=key_namespace, key_info=key_name) + _key_provider = MasterKeyInfo(provider_id=key_namespace, key_info=key_name) def on_encrypt(self, encryption_materials): """Generate a data key if not present and encrypt it using any available wrapping key. @@ -137,56 +197,26 @@ def on_encrypt(self, encryption_materials): :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - # Generate data key - plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) - - # Encrypt data key - encrypted_wrapped_key = self.wrapping_key.encrypt( - plaintext_data_key=plaintext_data_key, encryption_context=encryption_materials.encryption_context - ) - - encrypted_data_key = aws_encryption_sdk.internal.formatting.serialize.serialize_wrapped_key( - key_provider=self.key_provider, - wrapping_algorithm=self.wrapping_algorithm, - wrapping_key_id=self.key_name, - encrypted_wrapped_key=encrypted_wrapped_key, - ) - - # Update keyring trace - - # Update encryption materials - encryption_materials.data_encryption_key = RawDataKey( - key_provider=self.key_provider, data_key=plaintext_data_key - ) - encryption_materials.encrypted_data_keys.add(encrypted_data_key) + encryption_materials = on_encrypt_helper(encryption_materials, self._key_provider, self._wrapping_key, + self._wrapping_algorithm, self.key_name) return encryption_materials - def on_decrypt(self, decryption_materials): + def on_decrypt(self, decryption_materials, encrypted_data_keys): """Attempt to decrypt the encrypted data keys. - :param decryption_materials: Contains verification key, list of encrypted data keys. + :param decryption_materials: Contains verification key, algorithm, encryption context and keyring trace. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials - :returns: Contains verification key, list of encrypted data keys and decrypted data key. + :param encrypted_data_keys: List of encrypted data keys. + :type: List of `aws_encryption_sdk.structures.EncryptedDataKey` + :returns: Contains verification key, algorithm, data_encryption_key, encryption context and keyring trac :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials """ # Decrypt data key - if decryption_materials.encrypted_data_key.key_provider == self.key_provider: - encrypted_wrapped_key = aws_encryption_sdk.internal.formatting.deserialize.deserialize_wrapped_key( - wrapping_algorithm=self.wrapping_algorithm, - wrapping_key_id=self.key_name, - wrapped_encrypted_key=decryption_materials.encrypted_data_key, - ) - plaintext_data_key = self.wrapping_key.decrypt( - encrypted_wrapped_data_key=encrypted_wrapped_key, - encryption_context=decryption_materials.encryption_context, - ) - decryption_materials.data_key = DataKey( - key_provider=decryption_materials.encrypted_data_key.key_provider, - data_key=plaintext_data_key, - encrypted_data_key=decryption_materials.encrypted_data_key.encrypted_data_key, - ) - - # Update keyring trace + if encrypted_data_keys.key_provider == self._key_provider: + + decryption_materials = on_decrypt_helper(decryption_materials, self._wrapping_key, self._wrapping_algorithm, + self.key_name, encrypted_data_keys) + return decryption_materials From 8399fea1f110d7ff405e14856ed4c958644b03f7 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 27 Jun 2019 16:53:19 -0700 Subject: [PATCH 045/110] Updated with autoformat --- src/aws_encryption_sdk/keyring/raw_keyring.py | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 71321e08d..50b1661ca 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -13,18 +13,18 @@ """Resources required for Raw Keyrings.""" import os import struct -import six import attr +import six import aws_encryption_sdk.internal.formatting.deserialize import aws_encryption_sdk.internal.formatting.serialize +from aws_encryption_sdk.exceptions import EncryptKeyError from aws_encryption_sdk.identifiers import WrappingAlgorithm from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey from aws_encryption_sdk.internal.str_ops import to_bytes from aws_encryption_sdk.keyring.base import Keyring from aws_encryption_sdk.structures import DataKey, MasterKeyInfo, RawDataKey -from aws_encryption_sdk.exceptions import EncryptKeyError def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping_algorithm, key_name): @@ -39,9 +39,7 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping return EncryptKeyError("Unable to generate data encryption key.") # plaintext_data_key to RawDataKey - data_encryption_key = RawDataKey( - key_provider=key_provider, data_key=plaintext_data_key - ) + data_encryption_key = RawDataKey(key_provider=key_provider, data_key=plaintext_data_key) # Add generated data key to encryption_materials encryption_materials.add_data_encryption_key(data_encryption_key, encryption_materials.keyring_trace) @@ -59,7 +57,7 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping key_provider=key_provider, wrapping_algorithm=wrapping_algorithm, wrapping_key_id=key_name, - encrypted_wrapped_key=encrypted_wrapped_key + encrypted_wrapped_key=encrypted_wrapped_key, ) # Add encrypted data key to encryption_materials @@ -75,22 +73,19 @@ def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, ke # Wrapped EncryptedDataKey to deserialized EncryptedData encrypted_wrapped_key = aws_encryption_sdk.internal.formatting.deserialize.deserialize_wrapped_key( - wrapping_algorithm=wrapping_algorithm, - wrapping_key_id=key_name, - wrapped_encrypted_key=encrypted_data_key + wrapping_algorithm=wrapping_algorithm, wrapping_key_id=key_name, wrapped_encrypted_key=encrypted_data_key ) # EncryptedData to raw key string plaintext_data_key = wrapping_key.decrypt( - encrypted_wrapped_data_key=encrypted_wrapped_key, - encryption_context=decryption_materials.encryption_context + encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=decryption_materials.encryption_context ) # Update decryption materials data_encryption_key = DataKey( key_provider=encrypted_data_key.key_provider, data_key=plaintext_data_key, - encrypted_data_key=encrypted_data_key.encrypted_data_key + encrypted_data_key=encrypted_data_key.encrypted_data_key, ) decryption_materials.add_data_encryption_key(data_encryption_key, decryption_materials.keyring_trace) @@ -123,7 +118,7 @@ def __attrs_post_init__(self): to_bytes(self.key_name), # Tag Length is stored in bits, not bytes self._wrapping_algorithm.algorithm.tag_len * 8, - self._wrapping_algorithm.algorithm.iv_len + self._wrapping_algorithm.algorithm.iv_len, ) def on_encrypt(self, encryption_materials): @@ -137,8 +132,9 @@ def on_encrypt(self, encryption_materials): :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - encryption_materials = on_encrypt_helper(encryption_materials, self._key_provider, self._wrapping_key, - self._wrapping_algorithm, self.key_name) + encryption_materials = on_encrypt_helper( + encryption_materials, self._key_provider, self._wrapping_key, self._wrapping_algorithm, self.key_name + ) return encryption_materials @@ -160,8 +156,9 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): and len(encrypted_data_keys.key_provider.key_info) == expected_key_info_len and encrypted_data_keys.key_provider.key_info.startswith(self._key_info_prefix) ): - decryption_materials = on_decrypt_helper(decryption_materials, self._wrapping_key, self._wrapping_algorithm, - self.key_name, encrypted_data_keys) + decryption_materials = on_decrypt_helper( + decryption_materials, self._wrapping_key, self._wrapping_algorithm, self.key_name, encrypted_data_keys + ) return decryption_materials @@ -197,8 +194,9 @@ def on_encrypt(self, encryption_materials): :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - encryption_materials = on_encrypt_helper(encryption_materials, self._key_provider, self._wrapping_key, - self._wrapping_algorithm, self.key_name) + encryption_materials = on_encrypt_helper( + encryption_materials, self._key_provider, self._wrapping_key, self._wrapping_algorithm, self.key_name + ) return encryption_materials @@ -216,7 +214,8 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): # Decrypt data key if encrypted_data_keys.key_provider == self._key_provider: - decryption_materials = on_decrypt_helper(decryption_materials, self._wrapping_key, self._wrapping_algorithm, - self.key_name, encrypted_data_keys) + decryption_materials = on_decrypt_helper( + decryption_materials, self._wrapping_key, self._wrapping_algorithm, self.key_name, encrypted_data_keys + ) return decryption_materials From 38c756be632f9f948a9039b73fbb056510e5b73c Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Fri, 28 Jun 2019 09:44:27 -0700 Subject: [PATCH 046/110] Modified base --- src/aws_encryption_sdk/keyring/base.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index 3c4689d70..3192a5688 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -14,7 +14,10 @@ class Keyring(object): - """Parent interface for Keyring classes.""" + """Parent interface for Keyring classes. + + .. versionadded:: 1.5.0 + """ def on_encrypt(self, encryption_materials): """Generate a data key if not present and encrypt it using any available wrapping key. @@ -22,19 +25,22 @@ def on_encrypt(self, encryption_materials): :param encryption_materials: Contains signing key, encryption context and algorithm suite required to encrypt data key :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials - :returns: Contains signing key, unencrypted data key, encrypted data keys, + :returns: Encryption materials containing signing key, unencrypted data key, encrypted data keys, encryption context and algorithm suite required to encrypt data key :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials :raises NotImplementedError: if method is not implemented """ raise NotImplementedError("Keyring does not implement on_encrypt function") - def on_decrypt(self, decryption_materials): + def on_decrypt(self, decryption_materials, encrypted_data_keys): """Attempt to decrypt the encrypted data keys. - :param decryption_materials: Contains verification key, list of encrypted data keys. + :param decryption_materials: May contain verification key, algorithm, encryption context and keyring trace. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials - :returns: Contains verification key, list of encrypted data keys and decrypted data key. + :param encrypted_data_keys: List of encrypted data keys. + :type: Iterable of `aws_encryption_sdk.structures.EncryptedDataKey` + :returns: Decryption materials containing verification key, algorithm, data_encryption_key, + encryption context and keyring trace. :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials :raises NotImplementedError: if method is not implemented """ From 5005cfb9e69ac812aad83350e0178491fd963960 Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Fri, 28 Jun 2019 13:34:01 -0700 Subject: [PATCH 047/110] data encryption key must be set before encrypted data keys can be added to EncryptionMaterials --- .../materials_managers/__init__.py | 4 ++++ test/unit/test_material_managers.py | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/aws_encryption_sdk/materials_managers/__init__.py b/src/aws_encryption_sdk/materials_managers/__init__.py index 4ed77e315..916516dfc 100644 --- a/src/aws_encryption_sdk/materials_managers/__init__.py +++ b/src/aws_encryption_sdk/materials_managers/__init__.py @@ -263,9 +263,13 @@ def add_encrypted_data_key(self, encrypted_data_key, keyring_trace): :param EncryptedDataKey encrypted_data_key: Encrypted data key to add :param KeyringTrace keyring_trace: Trace of actions that a keyring performed while getting this encrypted data key + :raises AttributeError: if data encryption key is not set :raises InvalidKeyringTraceError: if keyring trace does not match generate action :raises InvalidKeyringTraceError: if keyring trace does not match data key encryptor """ + if self.data_encryption_key is None: + raise AttributeError("Data encryption key is not set.") + if KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY not in keyring_trace.flags: raise InvalidKeyringTraceError("Keyring flags do not match action.") diff --git a/test/unit/test_material_managers.py b/test/unit/test_material_managers.py index a1816fe10..6e2f9330e 100644 --- a/test/unit/test_material_managers.py +++ b/test/unit/test_material_managers.py @@ -301,15 +301,17 @@ def test_add_encrypted_data_key_success(): @pytest.mark.parametrize( - "encrypted_data_key, keyring_trace, exception_type, exception_message", + "mod_kwargs, encrypted_data_key, keyring_trace, exception_type, exception_message", ( ( + {}, _ENCRYPTED_DATA_KEY, KeyringTrace(wrapping_key=_ENCRYPTED_DATA_KEY.key_provider, flags=set()), InvalidKeyringTraceError, "Keyring flags do not match action.", ), ( + {}, EncryptedDataKey(key_provider=MasterKeyInfo(provider_id="a", key_info=b"b"), encrypted_data_key=b"asdf"), KeyringTrace( wrapping_key=MasterKeyInfo(provider_id="not a match", key_info=b"really not a match"), @@ -318,10 +320,19 @@ def test_add_encrypted_data_key_success(): InvalidKeyringTraceError, "Keyring trace does not match data key encryptor.", ), + ( + dict(data_encryption_key=_REMOVE), + _ENCRYPTED_DATA_KEY, + KeyringTrace( + wrapping_key=_ENCRYPTED_DATA_KEY.key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY} + ), + AttributeError, + "Data encryption key is not set.", + ), ), ) -def test_add_encrypted_data_key_fail(encrypted_data_key, keyring_trace, exception_type, exception_message): - kwargs = _copy_and_update_kwargs("EncryptionMaterials", {}) +def test_add_encrypted_data_key_fail(mod_kwargs, encrypted_data_key, keyring_trace, exception_type, exception_message): + kwargs = _copy_and_update_kwargs("EncryptionMaterials", mod_kwargs) materials = EncryptionMaterials(**kwargs) with pytest.raises(exception_type) as excinfo: From 242a3a3b101996ff950fdf58b33e266cdc557056 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Fri, 28 Jun 2019 16:22:38 -0700 Subject: [PATCH 048/110] Corrected tox and flake errors --- src/aws_encryption_sdk/keyring/raw_keyring.py | 57 ++++++++++++++----- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 50b1661ca..25b805727 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -11,6 +11,7 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Resources required for Raw Keyrings.""" + import os import struct @@ -28,6 +29,21 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping_algorithm, key_name): + """Helper function for the on_encrypt function of keyring. + + :param encryption_materials: Encryption materials for the keyring to modify. + :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials + :param key_provider: Information abput the key in the keyring. + :type key_provider: MasterKeyInfo + :param wrapping_key: Encryption key with which to wrap plaintext data key. + :type wrapping_key: WrappingKey + :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key. + :type wrapping_algorithm: WrappingAlgorithm + :param bytes key_name: Key ID. + :return: Optionally modified encryption materials. + :rtype encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials + """ + # Check if data key already exists if not encryption_materials.data_encryption_key: @@ -67,6 +83,21 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, key_name, encrypted_data_key): + """Helper function for the on_decrypt function of keyring. + + :param decryption_materials: Decryption materials for the keyring to modify. + :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials + :param wrapping_key: Encryption key with which to wrap plaintext data key. + :type wrapping_key: WrappingKey + :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key. + :type wrapping_algorithm: WrappingAlgorithm + :param bytes key_name: Key ID. + :param encrypted_data_key: Data key encrypted with a wrapping key. + :type encrypted_data_key: aws_encryption_sdk.structures.EncryptedDataKey + :return: Optionally modified decryption materials. + :rtype decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials + """ + # Check if plaintext data key exists if decryption_materials.data_key: return decryption_materials @@ -96,11 +127,11 @@ def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, ke class RawAESKeyring(Keyring): """Public class for Raw AES Keyring. - :param str key_namespace: String defining the keyring ID + :param str key_namespace: String defining the keyring. :param bytes key_name: Key ID - :param wrapping_key: Encryption key with which to wrap plaintext data key + :param wrapping_key: Encryption key with which to wrap plaintext data key. :type wrapping_key: WrappingKey - :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key + :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key. :type wrapping_algorithm: WrappingAlgorithm """ @@ -124,11 +155,9 @@ def __attrs_post_init__(self): def on_encrypt(self, encryption_materials): """Generate a data key if not present and encrypt it using any available wrapping key. - :param encryption_materials: Contains signing key, encryption context and algorithm suite - required to encrypt data key + :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials - :returns: Contains signing key, unencrypted data key, encrypted data keys, - encryption context and algorithm suite required to encrypt data key + :returns: Optionally modified encryption materials. :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ @@ -141,11 +170,11 @@ def on_encrypt(self, encryption_materials): def on_decrypt(self, decryption_materials, encrypted_data_keys): """Attempt to decrypt the encrypted data keys. - :param decryption_materials: Contains verification key, algorithm, encryption context and keyring trace. + :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials :param encrypted_data_keys: List of encrypted data keys. :type: List of `aws_encryption_sdk.structures.EncryptedDataKey` - :returns: Contains verification key, algorithm, data_encryption_key, encryption context and keyring trac + :returns: Optionally modified decryption materials. :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials """ @@ -186,11 +215,9 @@ class RawRSAKeyring(Keyring): def on_encrypt(self, encryption_materials): """Generate a data key if not present and encrypt it using any available wrapping key. - :param encryption_materials: Contains signing key, encryption context and algorithm suite - required to encrypt data key + :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials - :returns: Contains signing key, unencrypted data key, encrypted data keys, - encryption context and algorithm suite required to encrypt data key + :returns: Optionally modified encryption materials. :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ @@ -203,11 +230,11 @@ def on_encrypt(self, encryption_materials): def on_decrypt(self, decryption_materials, encrypted_data_keys): """Attempt to decrypt the encrypted data keys. - :param decryption_materials: Contains verification key, algorithm, encryption context and keyring trace. + :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials :param encrypted_data_keys: List of encrypted data keys. :type: List of `aws_encryption_sdk.structures.EncryptedDataKey` - :returns: Contains verification key, algorithm, data_encryption_key, encryption context and keyring trac + :returns: Optionally modified decryption materials. :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials """ From 26725671d11f213d150a7041130d08b8d39cf304 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Mon, 1 Jul 2019 09:25:38 -0700 Subject: [PATCH 049/110] Docstring error correction --- src/aws_encryption_sdk/keyring/raw_keyring.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 25b805727..ebe61f3a9 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -30,7 +30,6 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping_algorithm, key_name): """Helper function for the on_encrypt function of keyring. - :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials :param key_provider: Information abput the key in the keyring. @@ -84,7 +83,6 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, key_name, encrypted_data_key): """Helper function for the on_decrypt function of keyring. - :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials :param wrapping_key: Encryption key with which to wrap plaintext data key. @@ -126,7 +124,6 @@ def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, ke @attr.s class RawAESKeyring(Keyring): """Public class for Raw AES Keyring. - :param str key_namespace: String defining the keyring. :param bytes key_name: Key ID :param wrapping_key: Encryption key with which to wrap plaintext data key. @@ -154,7 +151,6 @@ def __attrs_post_init__(self): def on_encrypt(self, encryption_materials): """Generate a data key if not present and encrypt it using any available wrapping key. - :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials :returns: Optionally modified encryption materials. @@ -169,7 +165,6 @@ def on_encrypt(self, encryption_materials): def on_decrypt(self, decryption_materials, encrypted_data_keys): """Attempt to decrypt the encrypted data keys. - :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials :param encrypted_data_keys: List of encrypted data keys. @@ -194,7 +189,6 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): class RawRSAKeyring(Keyring): """Public class for Raw RSA Keyring. - :param str key_namespace: String defining the keyring ID :param bytes key_name: Key ID :param wrapping_key: Encryption key with which to wrap plaintext data key @@ -214,7 +208,6 @@ class RawRSAKeyring(Keyring): def on_encrypt(self, encryption_materials): """Generate a data key if not present and encrypt it using any available wrapping key. - :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials :returns: Optionally modified encryption materials. @@ -229,7 +222,6 @@ def on_encrypt(self, encryption_materials): def on_decrypt(self, decryption_materials, encrypted_data_keys): """Attempt to decrypt the encrypted data keys. - :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials :param encrypted_data_keys: List of encrypted data keys. From 2696183ed6d188a19e8669e3de4c2e3791048699 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Mon, 1 Jul 2019 10:27:41 -0700 Subject: [PATCH 050/110] Added docstrings and corrected errors --- src/aws_encryption_sdk/keyring/raw_keyring.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index ebe61f3a9..11b442777 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -30,6 +30,7 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping_algorithm, key_name): """Helper function for the on_encrypt function of keyring. + :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials :param key_provider: Information abput the key in the keyring. @@ -42,7 +43,6 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping :return: Optionally modified encryption materials. :rtype encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - # Check if data key already exists if not encryption_materials.data_encryption_key: @@ -83,6 +83,7 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, key_name, encrypted_data_key): """Helper function for the on_decrypt function of keyring. + :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials :param wrapping_key: Encryption key with which to wrap plaintext data key. @@ -95,7 +96,6 @@ def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, ke :return: Optionally modified decryption materials. :rtype decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials """ - # Check if plaintext data key exists if decryption_materials.data_key: return decryption_materials @@ -124,6 +124,7 @@ def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, ke @attr.s class RawAESKeyring(Keyring): """Public class for Raw AES Keyring. + :param str key_namespace: String defining the keyring. :param bytes key_name: Key ID :param wrapping_key: Encryption key with which to wrap plaintext data key. @@ -131,17 +132,16 @@ class RawAESKeyring(Keyring): :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key. :type wrapping_algorithm: WrappingAlgorithm """ - key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) key_name = attr.ib(hash=True, validator=attr.validators.instance_of(six.binary_type)) _wrapping_key = attr.ib(hash=True, repr=False, validator=attr.validators.instance_of(WrappingKey)) _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) def __attrs_post_init__(self): + """Prepares initial values not handled by attrs.""" + self._key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name) - _key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name) - - _key_info_prefix = struct.pack( + self._key_info_prefix = struct.pack( ">{}sII".format(len(self.key_name)), to_bytes(self.key_name), # Tag Length is stored in bits, not bytes @@ -151,12 +151,12 @@ def __attrs_post_init__(self): def on_encrypt(self, encryption_materials): """Generate a data key if not present and encrypt it using any available wrapping key. + :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials :returns: Optionally modified encryption materials. :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - encryption_materials = on_encrypt_helper( encryption_materials, self._key_provider, self._wrapping_key, self._wrapping_algorithm, self.key_name ) @@ -165,6 +165,7 @@ def on_encrypt(self, encryption_materials): def on_decrypt(self, decryption_materials, encrypted_data_keys): """Attempt to decrypt the encrypted data keys. + :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials :param encrypted_data_keys: List of encrypted data keys. @@ -172,7 +173,6 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): :returns: Optionally modified decryption materials. :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials """ - # Decrypt data key expected_key_info_len = len(self._key_info_prefix) + self._wrapping_algorithm.algorithm.iv_len if ( @@ -189,6 +189,7 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): class RawRSAKeyring(Keyring): """Public class for Raw RSA Keyring. + :param str key_namespace: String defining the keyring ID :param bytes key_name: Key ID :param wrapping_key: Encryption key with which to wrap plaintext data key @@ -198,7 +199,6 @@ class RawRSAKeyring(Keyring): :param key_provider: Complete information about the key in the keyring :type key_provider: MasterKeyInfo """ - key_namespace = attr.ib(validator=attr.validators.instance_of(str)) key_name = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) _wrapping_key = attr.ib(hash=True, repr=False, validator=attr.validators.instance_of(WrappingKey)) @@ -208,12 +208,12 @@ class RawRSAKeyring(Keyring): def on_encrypt(self, encryption_materials): """Generate a data key if not present and encrypt it using any available wrapping key. + :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials :returns: Optionally modified encryption materials. :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - encryption_materials = on_encrypt_helper( encryption_materials, self._key_provider, self._wrapping_key, self._wrapping_algorithm, self.key_name ) @@ -222,6 +222,7 @@ def on_encrypt(self, encryption_materials): def on_decrypt(self, decryption_materials, encrypted_data_keys): """Attempt to decrypt the encrypted data keys. + :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials :param encrypted_data_keys: List of encrypted data keys. @@ -229,7 +230,6 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): :returns: Optionally modified decryption materials. :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials """ - # Decrypt data key if encrypted_data_keys.key_provider == self._key_provider: From f1d1977e8987c2fcd7526c0d942815d622530a8e Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Mon, 1 Jul 2019 11:09:24 -0700 Subject: [PATCH 051/110] Some more changes in docstrings --- src/aws_encryption_sdk/keyring/raw_keyring.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 11b442777..a0d9de69a 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -132,6 +132,7 @@ class RawAESKeyring(Keyring): :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key. :type wrapping_algorithm: WrappingAlgorithm """ + key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) key_name = attr.ib(hash=True, validator=attr.validators.instance_of(six.binary_type)) _wrapping_key = attr.ib(hash=True, repr=False, validator=attr.validators.instance_of(WrappingKey)) @@ -199,6 +200,7 @@ class RawRSAKeyring(Keyring): :param key_provider: Complete information about the key in the keyring :type key_provider: MasterKeyInfo """ + key_namespace = attr.ib(validator=attr.validators.instance_of(str)) key_name = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) _wrapping_key = attr.ib(hash=True, repr=False, validator=attr.validators.instance_of(WrappingKey)) From f08239c4b2ed03b6621030b5492f0166e822cc66 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Mon, 1 Jul 2019 11:55:51 -0700 Subject: [PATCH 052/110] Updating base API --- src/aws_encryption_sdk/keyring/base.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index 3192a5688..770b53c0b 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -11,6 +11,14 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Base class interface for Keyrings.""" +from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials +from aws_encryption_sdk.structures import EncryptedDataKey + +try: # Python 3.5.0 and 3.5.1 have incompatible typing modules + from typing import Iterable # noqa pylint: disable=unused-import +except ImportError: # pragma: no cover + # We only actually need these imports when running the mypy checks + pass class Keyring(object): @@ -20,27 +28,26 @@ class Keyring(object): """ def on_encrypt(self, encryption_materials): + # type: (EncryptionMaterials) -> EncryptionMaterials """Generate a data key if not present and encrypt it using any available wrapping key. - :param encryption_materials: Contains signing key, encryption context and algorithm suite - required to encrypt data key + :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials - :returns: Encryption materials containing signing key, unencrypted data key, encrypted data keys, - encryption context and algorithm suite required to encrypt data key + :returns: Optionally modified encryption materials. :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials :raises NotImplementedError: if method is not implemented """ raise NotImplementedError("Keyring does not implement on_encrypt function") def on_decrypt(self, decryption_materials, encrypted_data_keys): + # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials """Attempt to decrypt the encrypted data keys. - :param decryption_materials: May contain verification key, algorithm, encryption context and keyring trace. + :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials :param encrypted_data_keys: List of encrypted data keys. - :type: Iterable of `aws_encryption_sdk.structures.EncryptedDataKey` - :returns: Decryption materials containing verification key, algorithm, data_encryption_key, - encryption context and keyring trace. + :type: Iterable of :class:`aws_encryption_sdk.structures.EncryptedDataKey` + :returns: Optionally modified decryption materials. :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials :raises NotImplementedError: if method is not implemented """ From 881cf5e1e3cb270f7618e4d1a99ae8fa4553d42e Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Mon, 1 Jul 2019 17:08:19 -0700 Subject: [PATCH 053/110] add signing/verification key checks to Encryption/DecryptionMaterials --- .../materials_managers/__init__.py | 5 +++++ test/unit/test_material_managers.py | 15 +++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/aws_encryption_sdk/materials_managers/__init__.py b/src/aws_encryption_sdk/materials_managers/__init__.py index 916516dfc..3dff7563a 100644 --- a/src/aws_encryption_sdk/materials_managers/__init__.py +++ b/src/aws_encryption_sdk/materials_managers/__init__.py @@ -20,6 +20,7 @@ from aws_encryption_sdk.exceptions import InvalidDataKeyError, InvalidKeyringTraceError, SignatureKeyError from aws_encryption_sdk.identifiers import Algorithm, KeyringTraceFlag +from aws_encryption_sdk.internal.crypto.authentication import Signer, Verifier from aws_encryption_sdk.internal.utils.streams import ROStream from aws_encryption_sdk.structures import DataKey, EncryptedDataKey, KeyringTrace, RawDataKey @@ -295,6 +296,8 @@ def add_signing_key(self, signing_key): if self.algorithm.signing_algorithm_info is None: raise SignatureKeyError("Algorithm suite does not support signing keys.") + Signer.from_key_bytes(algorithm=self.algorithm, key_bytes=signing_key) + self._setattr("signing_key", signing_key) @@ -408,4 +411,6 @@ def add_verification_key(self, verification_key): if self.algorithm.signing_algorithm_info is None: raise SignatureKeyError("Algorithm suite does not support signing keys.") + Verifier.from_key_bytes(algorithm=self.algorithm, key_bytes=verification_key) + self._setattr("verification_key", verification_key) diff --git a/test/unit/test_material_managers.py b/test/unit/test_material_managers.py index 6e2f9330e..e0cc55972 100644 --- a/test/unit/test_material_managers.py +++ b/test/unit/test_material_managers.py @@ -11,12 +11,16 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Test suite for aws_encryption_sdk.materials_managers""" + import pytest +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives.asymmetric import ec from mock import MagicMock from pytest_mock import mocker # noqa pylint: disable=unused-import from aws_encryption_sdk.exceptions import InvalidDataKeyError, InvalidKeyringTraceError, SignatureKeyError from aws_encryption_sdk.identifiers import AlgorithmSuite, KeyringTraceFlag +from aws_encryption_sdk.internal.crypto.authentication import Signer, Verifier from aws_encryption_sdk.internal.defaults import ALGORITHM from aws_encryption_sdk.internal.utils.streams import ROStream from aws_encryption_sdk.materials_managers import ( @@ -38,6 +42,9 @@ ) _RAW_DATA_KEY = RawDataKey.from_data_key(_DATA_KEY) _ENCRYPTED_DATA_KEY = EncryptedDataKey.from_data_key(_DATA_KEY) +_SIGNATURE_PRIVATE_KEY = ec.generate_private_key(ALGORITHM.signing_algorithm_info(), default_backend()) +_SIGNING_KEY = Signer(algorithm=ALGORITHM, key=_SIGNATURE_PRIVATE_KEY) +_VERIFICATION_KEY = Verifier(algorithm=ALGORITHM, key=_SIGNATURE_PRIVATE_KEY.public_key()) _VALID_KWARGS = { "CryptographicMaterials": dict( @@ -63,11 +70,11 @@ data_encryption_key=_DATA_KEY, encrypted_data_keys=set([]), encryption_context={}, - signing_key=b"", + signing_key=_SIGNING_KEY.key_bytes(), ), "DecryptionMaterialsRequest": dict(algorithm=ALGORITHM, encrypted_data_keys=set([]), encryption_context={}), "DecryptionMaterials": dict( - data_key=_DATA_KEY, verification_key=b"ex_verification_key", algorithm=ALGORITHM, encryption_context={} + data_key=_DATA_KEY, verification_key=_VERIFICATION_KEY.key_bytes(), algorithm=ALGORITHM, encryption_context={} ), } _REMOVE = object() @@ -345,7 +352,7 @@ def test_add_signing_key_success(): kwargs = _copy_and_update_kwargs("EncryptionMaterials", dict(signing_key=_REMOVE)) materials = EncryptionMaterials(**kwargs) - materials.add_signing_key(signing_key=b"") + materials.add_signing_key(signing_key=_SIGNING_KEY.key_bytes()) @pytest.mark.parametrize( @@ -374,7 +381,7 @@ def test_add_verification_key_success(): kwargs = _copy_and_update_kwargs("DecryptionMaterials", dict(verification_key=_REMOVE)) materials = DecryptionMaterials(**kwargs) - materials.add_verification_key(verification_key=b"") + materials.add_verification_key(verification_key=_VERIFICATION_KEY.key_bytes()) @pytest.mark.parametrize( From 5769efaf2ac58dbfbe1cbe6ea4fbb60438ad2f5c Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Mon, 1 Jul 2019 19:03:50 -0700 Subject: [PATCH 054/110] DecryptionMaterials.algorithm must be set before DecryptionMaterials.add_data_encryption_key can be called --- src/aws_encryption_sdk/materials_managers/__init__.py | 3 +++ test/unit/test_material_managers.py | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/src/aws_encryption_sdk/materials_managers/__init__.py b/src/aws_encryption_sdk/materials_managers/__init__.py index 3dff7563a..6d8669b22 100644 --- a/src/aws_encryption_sdk/materials_managers/__init__.py +++ b/src/aws_encryption_sdk/materials_managers/__init__.py @@ -391,6 +391,9 @@ def add_data_encryption_key(self, data_encryption_key, keyring_trace): :raises InvalidKeyringTraceError: if keyring trace does not match data key provider :raises InvalidDataKeyError: if data key length does not match algorithm suite """ + if self.algorithm is None: + raise AttributeError("Algorithm is not set") + self._add_data_encryption_key( data_encryption_key=data_encryption_key, keyring_trace=keyring_trace, diff --git a/test/unit/test_material_managers.py b/test/unit/test_material_managers.py index e0cc55972..dcfa984bf 100644 --- a/test/unit/test_material_managers.py +++ b/test/unit/test_material_managers.py @@ -277,6 +277,14 @@ def _add_data_encryption_key_test_cases(): InvalidDataKeyError, r"Invalid data key length *", ) + yield ( + DecryptionMaterials, + dict(data_encryption_key=_REMOVE, data_key=_REMOVE, algorithm=_REMOVE), + RawDataKey(key_provider=_RAW_DATA_KEY.key_provider, data_key=b"1234"), + KeyringTrace(wrapping_key=_RAW_DATA_KEY.key_provider, flags={required_flags}), + AttributeError, + "Algorithm is not set" + ) @pytest.mark.parametrize( From 00a767883dc8891a9e80e95f18ca447866fd10b8 Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Tue, 2 Jul 2019 11:52:29 -0700 Subject: [PATCH 055/110] update materials docs and typehints --- .../materials_managers/__init__.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/aws_encryption_sdk/materials_managers/__init__.py b/src/aws_encryption_sdk/materials_managers/__init__.py index 6d8669b22..ac63c4978 100644 --- a/src/aws_encryption_sdk/materials_managers/__init__.py +++ b/src/aws_encryption_sdk/materials_managers/__init__.py @@ -25,7 +25,7 @@ from aws_encryption_sdk.structures import DataKey, EncryptedDataKey, KeyringTrace, RawDataKey try: # Python 3.5.0 and 3.5.1 have incompatible typing modules - from typing import Iterable, Union # noqa pylint: disable=unused-import + from typing import Any, FrozenSet, Iterable, Tuple, Union # noqa pylint: disable=unused-import except ImportError: # pragma: no cover # We only actually need these imports when running the mypy checks pass @@ -77,9 +77,7 @@ class CryptographicMaterials(object): :param Algorithm algorithm: Algorithm to use for encrypting message :param dict encryption_context: Encryption context tied to `encrypted_data_keys` - :param DataKey data_encryption_key: Plaintext data key to use for encrypting message - :param encrypted_data_keys: List of encrypted data keys - :type encrypted_data_keys: list of :class:`EncryptedDataKey` + :param RawDataKey data_encryption_key: Plaintext data key to use for encrypting message :param keyring_trace: Any KeyRing trace entries :type keyring_trace: list of :class:`KeyringTrace` """ @@ -103,6 +101,7 @@ def __attrs_post_init__(self): self._initialized = True def __setattr__(self, key, value): + # type: (str, Any) -> None """Do not allow attributes to be changed once an instance is initialized.""" if self._initialized: raise AttributeError("can't set attribute") @@ -110,6 +109,7 @@ def __setattr__(self, key, value): self._setattr(key, value) def _setattr(self, key, value): + # type: (str, Any) -> None """Special __setattr__ to avoid having to perform multi-level super calls.""" super(CryptographicMaterials, self).__setattr__(key, value) @@ -150,6 +150,8 @@ def _add_data_encryption_key(self, data_encryption_key, keyring_trace, required_ :param RawDataKey data_encryption_key: Data encryption key :param KeyringTrace keyring_trace: Trace of actions that a keyring performed while getting this data encryption key + :param required_flags: Iterable of required flags + :type required_flags: iterable of :class:`KeyringTraceFlag` :raises AttributeError: if data encryption key is already set :raises InvalidKeyringTraceError: if keyring trace does not match required actions :raises InvalidKeyringTraceError: if keyring trace does not match data key provider @@ -166,6 +168,7 @@ def _add_data_encryption_key(self, data_encryption_key, keyring_trace, required_ @property def keyring_trace(self): + # type: () -> Tuple[KeyringTrace] """Return a read-only version of the keyring trace. :rtype: tuple @@ -229,6 +232,7 @@ def __init__( @property def encrypted_data_keys(self): + # type: () -> FrozenSet[EncryptedDataKey] """Return a read-only version of the encrypted data keys. :rtype: frozenset @@ -296,6 +300,7 @@ def add_signing_key(self, signing_key): if self.algorithm.signing_algorithm_info is None: raise SignatureKeyError("Algorithm suite does not support signing keys.") + # Verify that the signing key matches the algorithm Signer.from_key_bytes(algorithm=self.algorithm, key_bytes=signing_key) self._setattr("signing_key", signing_key) @@ -374,6 +379,7 @@ def __init__( @property def data_key(self): + # type: () -> RawDataKey """Backwards-compatible shim for access to data key.""" return self.data_encryption_key @@ -414,6 +420,7 @@ def add_verification_key(self, verification_key): if self.algorithm.signing_algorithm_info is None: raise SignatureKeyError("Algorithm suite does not support signing keys.") + # Verify that the verification key matches the algorithm Verifier.from_key_bytes(algorithm=self.algorithm, key_bytes=verification_key) self._setattr("verification_key", verification_key) From 36edf5b6ed8a0d463d9c01507e5ccd3c33fc4863 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 2 Jul 2019 15:22:54 -0700 Subject: [PATCH 056/110] Made all suggested changes --- src/aws_encryption_sdk/keyring/raw_keyring.py | 173 +++++++++++++----- 1 file changed, 124 insertions(+), 49 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index a0d9de69a..344920196 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -13,27 +13,58 @@ """Resources required for Raw Keyrings.""" import os -import struct +import logging import attr import six -import aws_encryption_sdk.internal.formatting.deserialize -import aws_encryption_sdk.internal.formatting.serialize +from aws_encryption_sdk.internal.formatting.deserialize import deserialize_wrapped_key +from aws_encryption_sdk.internal.formatting.serialize import serialize_wrapped_key, serialize_raw_master_key_prefix from aws_encryption_sdk.exceptions import EncryptKeyError -from aws_encryption_sdk.identifiers import WrappingAlgorithm +from aws_encryption_sdk.identifiers import WrappingAlgorithm, EncryptionKeyType from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey -from aws_encryption_sdk.internal.str_ops import to_bytes from aws_encryption_sdk.keyring.base import Keyring -from aws_encryption_sdk.structures import DataKey, MasterKeyInfo, RawDataKey +from aws_encryption_sdk.structures import MasterKeyInfo, RawDataKey, KeyringTrace +from aws_encryption_sdk.key_providers.raw import RawMasterKey +try: # Python 3.5.0 and 3.5.1 have incompatible typing modules + from typing import Iterable # noqa pylint: disable=unused-import +except ImportError: # pragma: no cover + # We only actually need these imports when running the mypy checks + pass -def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping_algorithm, key_name): + +def get_key_info_prefix(key_namespace, key_name, wrapping_key): + # type: (str, bytes, WrappingKey) -> six.binary_type + """Helper function to get key info prefix + + :param str key_namespace: String defining the keyring. + :param bytes key_name: Key ID + :param wrapping_key: Encryption key with which to wrap plaintext data key. + :type wrapping_key: WrappingKey + :return: Serialized key_info prefix + :rtype: bytes + """ + key_info_prefix = serialize_raw_master_key_prefix(RawMasterKey(provider_id=key_namespace, + key_id=key_name, + wrapping_key=wrapping_key + ) + ) + return key_info_prefix + + +def on_encrypt_helper(encryption_materials, # type: EncryptionMaterials + key_provider, # type: MasterKeyInfo + wrapping_key, # type: WrappingKey + wrapping_algorithm, # type: WrappingAlgorithm + key_name # type: bytes + ): + # type: (...) -> EncryptionMaterials """Helper function for the on_encrypt function of keyring. :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials - :param key_provider: Information abput the key in the keyring. + :param key_provider: Information about the key in the keyring. :type key_provider: MasterKeyInfo :param wrapping_key: Encryption key with which to wrap plaintext data key. :type wrapping_key: WrappingKey @@ -43,6 +74,12 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping :return: Optionally modified encryption materials. :rtype encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials """ + # Create a keyring trace + keyring_trace = KeyringTrace( + wrapping_key=key_provider, + flags=set() + ) + # Check if data key already exists if not encryption_materials.data_encryption_key: @@ -57,7 +94,7 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping data_encryption_key = RawDataKey(key_provider=key_provider, data_key=plaintext_data_key) # Add generated data key to encryption_materials - encryption_materials.add_data_encryption_key(data_encryption_key, encryption_materials.keyring_trace) + encryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) else: plaintext_data_key = encryption_materials.data_encryption_key @@ -68,7 +105,7 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping ) # EncryptedData to EncryptedDataKey - encrypted_data_key = aws_encryption_sdk.internal.formatting.serialize.serialize_wrapped_key( + encrypted_data_key = serialize_wrapped_key( key_provider=key_provider, wrapping_algorithm=wrapping_algorithm, wrapping_key_id=key_name, @@ -76,16 +113,25 @@ def on_encrypt_helper(encryption_materials, key_provider, wrapping_key, wrapping ) # Add encrypted data key to encryption_materials - encryption_materials.add_encrypted_data_key(encrypted_data_key, encryption_materials.keyring_trace) + encryption_materials.add_encrypted_data_key(encrypted_data_key, keyring_trace) return encryption_materials -def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, key_name, encrypted_data_key): +def on_decrypt_helper(decryption_materials, # type: DecryptionMaterials + key_provider, # type: MasterKeyInfo + wrapping_key, # type: WrappingKey + wrapping_algorithm, # type: WrappingAlgorithm + key_name, # type: bytes + encrypted_data_key # type: EncryptedDataKey + ): + # type: (...) -> DecryptionMaterials """Helper function for the on_decrypt function of keyring. :param decryption_materials: Decryption materials for the keyring to modify. :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials + :param key_provider: Information about the key in the keyring. + :type key_provider: MasterKeyInfo :param wrapping_key: Encryption key with which to wrap plaintext data key. :type wrapping_key: WrappingKey :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key. @@ -96,27 +142,37 @@ def on_decrypt_helper(decryption_materials, wrapping_key, wrapping_algorithm, ke :return: Optionally modified decryption materials. :rtype decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials """ + # Create a keyring trace + keyring_trace = KeyringTrace( + wrapping_key=key_provider, + flags=set() + ) + # Check if plaintext data key exists if decryption_materials.data_key: return decryption_materials # Wrapped EncryptedDataKey to deserialized EncryptedData - encrypted_wrapped_key = aws_encryption_sdk.internal.formatting.deserialize.deserialize_wrapped_key( + encrypted_wrapped_key = deserialize_wrapped_key( wrapping_algorithm=wrapping_algorithm, wrapping_key_id=key_name, wrapped_encrypted_key=encrypted_data_key ) # EncryptedData to raw key string - plaintext_data_key = wrapping_key.decrypt( - encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=decryption_materials.encryption_context - ) + try: + plaintext_data_key = wrapping_key.decrypt( + encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=decryption_materials.encryption_context + ) + except Exception as error: + logging.ERROR(error.__class__.__name__, ':', str(error)) + return decryption_materials # Update decryption materials - data_encryption_key = DataKey( - key_provider=encrypted_data_key.key_provider, - data_key=plaintext_data_key, - encrypted_data_key=encrypted_data_key.encrypted_data_key, + data_encryption_key = RawDataKey( + key_provider=MasterKeyInfo(provider_id=key_provider.provider_id, + key_info=key_name), + data_key=plaintext_data_key ) - decryption_materials.add_data_encryption_key(data_encryption_key, decryption_materials.keyring_trace) + decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) return decryption_materials @@ -134,23 +190,26 @@ class RawAESKeyring(Keyring): """ key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) - key_name = attr.ib(hash=True, validator=attr.validators.instance_of(six.binary_type)) - _wrapping_key = attr.ib(hash=True, repr=False, validator=attr.validators.instance_of(WrappingKey)) + key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) + _wrapping_key = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingKey)) _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) def __attrs_post_init__(self): + # type: () -> None """Prepares initial values not handled by attrs.""" self._key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name) - self._key_info_prefix = struct.pack( - ">{}sII".format(len(self.key_name)), - to_bytes(self.key_name), - # Tag Length is stored in bits, not bytes - self._wrapping_algorithm.algorithm.tag_len * 8, - self._wrapping_algorithm.algorithm.iv_len, - ) + self._key_info_prefix = get_key_info_prefix(key_namespace=self.key_namespace, + key_name=self.key_name, + wrapping_key=WrappingKey( + wrapping_algorithm=self._wrapping_algorithm, + wrapping_key=self._wrapping_key, + wrapping_key_type=EncryptionKeyType.SYMMETRIC + ) + ) def on_encrypt(self, encryption_materials): + # type: (EncryptionMaterials) -> EncryptionMaterials """Generate a data key if not present and encrypt it using any available wrapping key. :param encryption_materials: Encryption materials for the keyring to modify. @@ -159,12 +218,15 @@ def on_encrypt(self, encryption_materials): :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ encryption_materials = on_encrypt_helper( - encryption_materials, self._key_provider, self._wrapping_key, self._wrapping_algorithm, self.key_name + encryption_materials=encryption_materials, key_provider=self._key_provider, + wrapping_key=self._wrapping_key, wrapping_algorithm=self._wrapping_algorithm, + key_name=self.key_name ) return encryption_materials def on_decrypt(self, decryption_materials, encrypted_data_keys): + # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials """Attempt to decrypt the encrypted data keys. :param decryption_materials: Decryption materials for the keyring to modify. @@ -176,14 +238,18 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): """ # Decrypt data key expected_key_info_len = len(self._key_info_prefix) + self._wrapping_algorithm.algorithm.iv_len - if ( - encrypted_data_keys.key_provider.provider_id == self._key_provider.provider_id - and len(encrypted_data_keys.key_provider.key_info) == expected_key_info_len - and encrypted_data_keys.key_provider.key_info.startswith(self._key_info_prefix) - ): - decryption_materials = on_decrypt_helper( - decryption_materials, self._wrapping_key, self._wrapping_algorithm, self.key_name, encrypted_data_keys - ) + for key in encrypted_data_keys: + if (key.key_provider.provider_id == self._key_provider.provider_id + and len(key.key_provider.key_info) == expected_key_info_len + and key.key_provider.key_info.startswith(self._key_info_prefix) + ): + decryption_materials = on_decrypt_helper( + decryption_materials=decryption_materials, key_provider=self._key_provider, + wrapping_key=self._wrapping_key, wrapping_algorithm=self._wrapping_algorithm, + key_name=self.key_name, encrypted_data_key=key + ) + if decryption_materials.data_key: + return decryption_materials return decryption_materials @@ -201,14 +267,18 @@ class RawRSAKeyring(Keyring): :type key_provider: MasterKeyInfo """ - key_namespace = attr.ib(validator=attr.validators.instance_of(str)) - key_name = attr.ib(hash=True, validator=attr.validators.instance_of(bytes)) - _wrapping_key = attr.ib(hash=True, repr=False, validator=attr.validators.instance_of(WrappingKey)) + key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) + key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) + _wrapping_key = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingKey)) _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) - _key_provider = MasterKeyInfo(provider_id=key_namespace, key_info=key_name) + def __attrs_post_init__(self): + # type: () -> None + """Prepares initial values not handled by attrs.""" + self._key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name) def on_encrypt(self, encryption_materials): + # type: (EncryptionMaterials) -> EncryptionMaterials """Generate a data key if not present and encrypt it using any available wrapping key. :param encryption_materials: Encryption materials for the keyring to modify. @@ -217,12 +287,15 @@ def on_encrypt(self, encryption_materials): :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ encryption_materials = on_encrypt_helper( - encryption_materials, self._key_provider, self._wrapping_key, self._wrapping_algorithm, self.key_name + encryption_materials=encryption_materials, key_provider=self._key_provider, + wrapping_key=self._wrapping_key, wrapping_algorithm=self._wrapping_algorithm, + key_name=self.key_name ) return encryption_materials def on_decrypt(self, decryption_materials, encrypted_data_keys): + # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials """Attempt to decrypt the encrypted data keys. :param decryption_materials: Decryption materials for the keyring to modify. @@ -233,10 +306,12 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials """ # Decrypt data key - if encrypted_data_keys.key_provider == self._key_provider: - - decryption_materials = on_decrypt_helper( - decryption_materials, self._wrapping_key, self._wrapping_algorithm, self.key_name, encrypted_data_keys - ) + for key in encrypted_data_keys: + if key.key_provider == self._key_provider: + decryption_materials = on_decrypt_helper( + decryption_materials=decryption_materials, key_provider=self._key_provider, + wrapping_key=self._wrapping_key, wrapping_algorithm=self._wrapping_algorithm, + key_name=self.key_name, encrypted_data_key=key + ) return decryption_materials From 98cf7918ffae2cd767c411262c5cd3c4e7a43b23 Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Tue, 2 Jul 2019 18:11:45 -0700 Subject: [PATCH 057/110] EncryptionMaterials must not be initialized with encrypted_data_keys but no data_encryption_key --- .../materials_managers/__init__.py | 3 +++ test/unit/test_material_managers.py | 19 +++++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/aws_encryption_sdk/materials_managers/__init__.py b/src/aws_encryption_sdk/materials_managers/__init__.py index ac63c4978..3045d6a50 100644 --- a/src/aws_encryption_sdk/materials_managers/__init__.py +++ b/src/aws_encryption_sdk/materials_managers/__init__.py @@ -220,6 +220,9 @@ def __init__( if encryption_context is None: raise TypeError("encryption_context must not be None") + if data_encryption_key is None and encrypted_data_keys is not None: + raise TypeError("encrypted_data_keys cannot be provided without data_encryption_key") + super(EncryptionMaterials, self).__init__( algorithm=algorithm, encryption_context=encryption_context, diff --git a/test/unit/test_material_managers.py b/test/unit/test_material_managers.py index dcfa984bf..e75cd7c44 100644 --- a/test/unit/test_material_managers.py +++ b/test/unit/test_material_managers.py @@ -104,6 +104,7 @@ def _copy_and_update_kwargs(class_name, mod_kwargs): (EncryptionMaterials, dict(algorithm=None)), (EncryptionMaterials, dict(encryption_context=None)), (EncryptionMaterials, dict(signing_key=u"not bytes or None")), + (EncryptionMaterials, dict(data_encryption_key=_REMOVE)), (DecryptionMaterialsRequest, dict(algorithm=None)), (DecryptionMaterialsRequest, dict(encrypted_data_keys=None)), (DecryptionMaterialsRequest, dict(encryption_context=None)), @@ -229,7 +230,9 @@ def test_immutable_encrypted_data_keys(): ), ) def test_add_data_encryption_key_success(material_class, flag): - kwargs = _copy_and_update_kwargs(material_class.__name__, dict(data_encryption_key=_REMOVE, data_key=_REMOVE)) + kwargs = _copy_and_update_kwargs( + material_class.__name__, dict(data_encryption_key=_REMOVE, data_key=_REMOVE, encrypted_data_keys=_REMOVE) + ) materials = material_class(**kwargs) materials.add_data_encryption_key( @@ -247,7 +250,7 @@ def _add_data_encryption_key_test_cases(): ): yield ( material_class, - dict(data_encryption_key=_RAW_DATA_KEY, data_key=_REMOVE), + dict(data_encryption_key=_RAW_DATA_KEY, data_key=_REMOVE, encrypted_data_keys=_REMOVE), _RAW_DATA_KEY, KeyringTrace(wrapping_key=_RAW_DATA_KEY.key_provider, flags={required_flags}), AttributeError, @@ -255,7 +258,7 @@ def _add_data_encryption_key_test_cases(): ) yield ( material_class, - dict(data_encryption_key=_REMOVE, data_key=_REMOVE), + dict(data_encryption_key=_REMOVE, data_key=_REMOVE, encrypted_data_keys=_REMOVE), _RAW_DATA_KEY, KeyringTrace(wrapping_key=_RAW_DATA_KEY.key_provider, flags=set()), InvalidKeyringTraceError, @@ -263,7 +266,7 @@ def _add_data_encryption_key_test_cases(): ) yield ( material_class, - dict(data_encryption_key=_REMOVE, data_key=_REMOVE), + dict(data_encryption_key=_REMOVE, data_key=_REMOVE, encrypted_data_keys=_REMOVE), RawDataKey(key_provider=MasterKeyInfo(provider_id="a", key_info=b"b"), data_key=b"asdf"), KeyringTrace(wrapping_key=MasterKeyInfo(provider_id="c", key_info=b"d"), flags={required_flags}), InvalidKeyringTraceError, @@ -271,7 +274,7 @@ def _add_data_encryption_key_test_cases(): ) yield ( material_class, - dict(data_encryption_key=_REMOVE, data_key=_REMOVE), + dict(data_encryption_key=_REMOVE, data_key=_REMOVE, encrypted_data_keys=_REMOVE), RawDataKey(key_provider=_RAW_DATA_KEY.key_provider, data_key=b"1234"), KeyringTrace(wrapping_key=_RAW_DATA_KEY.key_provider, flags={required_flags}), InvalidDataKeyError, @@ -279,11 +282,11 @@ def _add_data_encryption_key_test_cases(): ) yield ( DecryptionMaterials, - dict(data_encryption_key=_REMOVE, data_key=_REMOVE, algorithm=_REMOVE), + dict(data_encryption_key=_REMOVE, data_key=_REMOVE, encrypted_data_keys=_REMOVE, algorithm=_REMOVE), RawDataKey(key_provider=_RAW_DATA_KEY.key_provider, data_key=b"1234"), KeyringTrace(wrapping_key=_RAW_DATA_KEY.key_provider, flags={required_flags}), AttributeError, - "Algorithm is not set" + "Algorithm is not set", ) @@ -336,7 +339,7 @@ def test_add_encrypted_data_key_success(): "Keyring trace does not match data key encryptor.", ), ( - dict(data_encryption_key=_REMOVE), + dict(data_encryption_key=_REMOVE, encrypted_data_keys=_REMOVE), _ENCRYPTED_DATA_KEY, KeyringTrace( wrapping_key=_ENCRYPTED_DATA_KEY.key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY} From e03f38bbb7a7412f232c9daf314d58da6324cdc3 Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Tue, 2 Jul 2019 18:44:00 -0700 Subject: [PATCH 058/110] add is_complete properties to EncryptionMaterials and DecryptionMaterials --- .../materials_managers/__init__.py | 39 ++++++++++++ test/unit/test_material_managers.py | 62 +++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/src/aws_encryption_sdk/materials_managers/__init__.py b/src/aws_encryption_sdk/materials_managers/__init__.py index 3045d6a50..a6609199a 100644 --- a/src/aws_encryption_sdk/materials_managers/__init__.py +++ b/src/aws_encryption_sdk/materials_managers/__init__.py @@ -223,6 +223,9 @@ def __init__( if data_encryption_key is None and encrypted_data_keys is not None: raise TypeError("encrypted_data_keys cannot be provided without data_encryption_key") + if encrypted_data_keys is None: + encrypted_data_keys = [] + super(EncryptionMaterials, self).__init__( algorithm=algorithm, encryption_context=encryption_context, @@ -242,6 +245,24 @@ def encrypted_data_keys(self): """ return frozenset(self._encrypted_data_keys) + @property + def is_complete(self): + # type: () -> bool + """Determine whether these materials are sufficiently complete for use as decryption materials. + + :rtype: bool + """ + if self.data_encryption_key is None: + return False + + if not self.encrypted_data_keys: + return False + + if self.algorithm.signing_algorithm_info is not None and self.signing_key is None: + return False + + return True + def add_data_encryption_key(self, data_encryption_key, keyring_trace): # type: (Union[DataKey, RawDataKey], KeyringTrace) -> None """Add a plaintext data encryption key. @@ -380,6 +401,24 @@ def __init__( self._setattr("verification_key", verification_key) attr.validate(self) + @property + def is_complete(self): + # type: () -> bool + """Determine whether these materials are sufficiently complete for use as decryption materials. + + :rtype: bool + """ + if None in (self.algorithm, self.encryption_context): + return False + + if self.data_encryption_key is None: + return False + + if self.algorithm.signing_algorithm_info is not None and self.verification_key is None: + return False + + return True + @property def data_key(self): # type: () -> RawDataKey diff --git a/test/unit/test_material_managers.py b/test/unit/test_material_managers.py index e75cd7c44..2f64f3c74 100644 --- a/test/unit/test_material_managers.py +++ b/test/unit/test_material_managers.py @@ -215,6 +215,16 @@ def test_immutable_keyring_trace(material_class): materials.keyring_trace.append(42) +@pytest.mark.parametrize("material_class", (CryptographicMaterials, EncryptionMaterials, DecryptionMaterials)) +def test_empty_keyring_trace(material_class): + materials = material_class(**_copy_and_update_kwargs(material_class.__name__, dict(keyring_trace=_REMOVE))) + + trace = materials.keyring_trace + + assert isinstance(trace, tuple) + assert not trace + + def test_immutable_encrypted_data_keys(): materials = EncryptionMaterials(**_VALID_KWARGS["EncryptionMaterials"]) @@ -222,6 +232,15 @@ def test_immutable_encrypted_data_keys(): materials.encrypted_data_keys.add(42) +def test_empty_encrypted_data_keys(): + materials = EncryptionMaterials(**_copy_and_update_kwargs("EncryptionMaterials", dict(encrypted_data_keys=_REMOVE))) + + edks = materials.encrypted_data_keys + + assert isinstance(edks, frozenset) + assert not edks + + @pytest.mark.parametrize( "material_class, flag", ( @@ -415,3 +434,46 @@ def test_add_verification_key_fail(mod_kwargs, verification_key, exception_type, materials.add_verification_key(verification_key=verification_key) excinfo.match(exception_message) + + +def test_decryption_materials_is_complete(): + materials = DecryptionMaterials(**_copy_and_update_kwargs("DecryptionMaterials", {})) + + assert materials.is_complete + + +@pytest.mark.parametrize( + "mod_kwargs", + ( + dict(algorithm=_REMOVE), + dict(encryption_context=_REMOVE), + dict(data_encryption_key=_REMOVE, data_key=_REMOVE), + dict(verification_key=_REMOVE), + ), +) +def test_decryption_materials_is_not_complete(mod_kwargs): + kwargs = _copy_and_update_kwargs("DecryptionMaterials", mod_kwargs) + materials = DecryptionMaterials(**kwargs) + + assert not materials.is_complete + + +def test_encryption_materials_is_complete(): + materials = EncryptionMaterials(**_copy_and_update_kwargs("EncryptionMaterials", {})) + + assert materials.is_complete + + +@pytest.mark.parametrize( + "mod_kwargs", + ( + dict(data_encryption_key=_REMOVE, encrypted_data_keys=_REMOVE), + dict(encrypted_data_keys=_REMOVE), + dict(signing_key=_REMOVE), + ), +) +def test_encryption_materials_is_not_complete(mod_kwargs): + kwargs = _copy_and_update_kwargs("EncryptionMaterials", mod_kwargs) + materials = EncryptionMaterials(**kwargs) + + assert not materials.is_complete From f99ac6c19b0312d26e5a25e1ed3c603f489922a5 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Wed, 3 Jul 2019 09:24:19 -0700 Subject: [PATCH 059/110] Corrected tox and flake8 errors --- src/aws_encryption_sdk/keyring/raw_keyring.py | 119 +++++++++--------- 1 file changed, 62 insertions(+), 57 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 344920196..0831dc757 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -12,20 +12,21 @@ # language governing permissions and limitations under the License. """Resources required for Raw Keyrings.""" -import os import logging +import os import attr import six -from aws_encryption_sdk.internal.formatting.deserialize import deserialize_wrapped_key -from aws_encryption_sdk.internal.formatting.serialize import serialize_wrapped_key, serialize_raw_master_key_prefix from aws_encryption_sdk.exceptions import EncryptKeyError -from aws_encryption_sdk.identifiers import WrappingAlgorithm, EncryptionKeyType +from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey -from aws_encryption_sdk.keyring.base import Keyring -from aws_encryption_sdk.structures import MasterKeyInfo, RawDataKey, KeyringTrace +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.keyring.base import Keyring +from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials +from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey try: # Python 3.5.0 and 3.5.1 have incompatible typing modules from typing import Iterable # noqa pylint: disable=unused-import @@ -45,20 +46,19 @@ def get_key_info_prefix(key_namespace, key_name, wrapping_key): :return: Serialized key_info prefix :rtype: bytes """ - key_info_prefix = serialize_raw_master_key_prefix(RawMasterKey(provider_id=key_namespace, - key_id=key_name, - wrapping_key=wrapping_key - ) - ) + key_info_prefix = serialize_raw_master_key_prefix( + RawMasterKey(provider_id=key_namespace, key_id=key_name, wrapping_key=wrapping_key) + ) return key_info_prefix -def on_encrypt_helper(encryption_materials, # type: EncryptionMaterials - key_provider, # type: MasterKeyInfo - wrapping_key, # type: WrappingKey - wrapping_algorithm, # type: WrappingAlgorithm - key_name # type: bytes - ): +def on_encrypt_helper( + encryption_materials, # type: EncryptionMaterials + key_provider, # type: MasterKeyInfo + wrapping_key, # type: WrappingKey + wrapping_algorithm, # type: WrappingAlgorithm + key_name, # type: bytes +): # type: (...) -> EncryptionMaterials """Helper function for the on_encrypt function of keyring. @@ -75,10 +75,7 @@ def on_encrypt_helper(encryption_materials, # type: EncryptionMaterials :rtype encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials """ # Create a keyring trace - keyring_trace = KeyringTrace( - wrapping_key=key_provider, - flags=set() - ) + keyring_trace = KeyringTrace(wrapping_key=key_provider, flags=set()) # Check if data key already exists if not encryption_materials.data_encryption_key: @@ -118,13 +115,14 @@ def on_encrypt_helper(encryption_materials, # type: EncryptionMaterials return encryption_materials -def on_decrypt_helper(decryption_materials, # type: DecryptionMaterials - key_provider, # type: MasterKeyInfo - wrapping_key, # type: WrappingKey - wrapping_algorithm, # type: WrappingAlgorithm - key_name, # type: bytes - encrypted_data_key # type: EncryptedDataKey - ): +def on_decrypt_helper( + decryption_materials, # type: DecryptionMaterials + key_provider, # type: MasterKeyInfo + wrapping_key, # type: WrappingKey + wrapping_algorithm, # type: WrappingAlgorithm + key_name, # type: bytes + encrypted_data_key, # type: EncryptedDataKey +): # type: (...) -> DecryptionMaterials """Helper function for the on_decrypt function of keyring. @@ -143,10 +141,7 @@ def on_decrypt_helper(decryption_materials, # type: DecryptionMaterials :rtype decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials """ # Create a keyring trace - keyring_trace = KeyringTrace( - wrapping_key=key_provider, - flags=set() - ) + keyring_trace = KeyringTrace(wrapping_key=key_provider, flags=set()) # Check if plaintext data key exists if decryption_materials.data_key: @@ -163,14 +158,12 @@ def on_decrypt_helper(decryption_materials, # type: DecryptionMaterials encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=decryption_materials.encryption_context ) except Exception as error: - logging.ERROR(error.__class__.__name__, ':', str(error)) + logging.ERROR(error.__class__.__name__, ":", str(error)) return decryption_materials # Update decryption materials data_encryption_key = RawDataKey( - key_provider=MasterKeyInfo(provider_id=key_provider.provider_id, - key_info=key_name), - data_key=plaintext_data_key + key_provider=MasterKeyInfo(provider_id=key_provider.provider_id, key_info=key_name), data_key=plaintext_data_key ) decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) @@ -199,14 +192,15 @@ def __attrs_post_init__(self): """Prepares initial values not handled by attrs.""" self._key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name) - self._key_info_prefix = get_key_info_prefix(key_namespace=self.key_namespace, - key_name=self.key_name, - wrapping_key=WrappingKey( - wrapping_algorithm=self._wrapping_algorithm, - wrapping_key=self._wrapping_key, - wrapping_key_type=EncryptionKeyType.SYMMETRIC - ) - ) + self._key_info_prefix = get_key_info_prefix( + key_namespace=self.key_namespace, + key_name=self.key_name, + wrapping_key=WrappingKey( + wrapping_algorithm=self._wrapping_algorithm, + wrapping_key=self._wrapping_key, + wrapping_key_type=EncryptionKeyType.SYMMETRIC, + ), + ) def on_encrypt(self, encryption_materials): # type: (EncryptionMaterials) -> EncryptionMaterials @@ -218,9 +212,11 @@ def on_encrypt(self, encryption_materials): :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ encryption_materials = on_encrypt_helper( - encryption_materials=encryption_materials, key_provider=self._key_provider, - wrapping_key=self._wrapping_key, wrapping_algorithm=self._wrapping_algorithm, - key_name=self.key_name + encryption_materials=encryption_materials, + key_provider=self._key_provider, + wrapping_key=self._wrapping_key, + wrapping_algorithm=self._wrapping_algorithm, + key_name=self.key_name, ) return encryption_materials @@ -239,14 +235,18 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): # Decrypt data key expected_key_info_len = len(self._key_info_prefix) + self._wrapping_algorithm.algorithm.iv_len for key in encrypted_data_keys: - if (key.key_provider.provider_id == self._key_provider.provider_id + if ( + key.key_provider.provider_id == self._key_provider.provider_id and len(key.key_provider.key_info) == expected_key_info_len and key.key_provider.key_info.startswith(self._key_info_prefix) ): decryption_materials = on_decrypt_helper( - decryption_materials=decryption_materials, key_provider=self._key_provider, - wrapping_key=self._wrapping_key, wrapping_algorithm=self._wrapping_algorithm, - key_name=self.key_name, encrypted_data_key=key + decryption_materials=decryption_materials, + key_provider=self._key_provider, + wrapping_key=self._wrapping_key, + wrapping_algorithm=self._wrapping_algorithm, + key_name=self.key_name, + encrypted_data_key=key, ) if decryption_materials.data_key: return decryption_materials @@ -287,9 +287,11 @@ def on_encrypt(self, encryption_materials): :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ encryption_materials = on_encrypt_helper( - encryption_materials=encryption_materials, key_provider=self._key_provider, - wrapping_key=self._wrapping_key, wrapping_algorithm=self._wrapping_algorithm, - key_name=self.key_name + encryption_materials=encryption_materials, + key_provider=self._key_provider, + wrapping_key=self._wrapping_key, + wrapping_algorithm=self._wrapping_algorithm, + key_name=self.key_name, ) return encryption_materials @@ -309,9 +311,12 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): for key in encrypted_data_keys: if key.key_provider == self._key_provider: decryption_materials = on_decrypt_helper( - decryption_materials=decryption_materials, key_provider=self._key_provider, - wrapping_key=self._wrapping_key, wrapping_algorithm=self._wrapping_algorithm, - key_name=self.key_name, encrypted_data_key=key + decryption_materials=decryption_materials, + key_provider=self._key_provider, + wrapping_key=self._wrapping_key, + wrapping_algorithm=self._wrapping_algorithm, + key_name=self.key_name, + encrypted_data_key=key, ) return decryption_materials From b928fd29444bc0f480a82a0d1f32c0e6121f2137 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Mon, 8 Jul 2019 11:36:36 -0700 Subject: [PATCH 060/110] Minor change in raw-keyrings --- src/aws_encryption_sdk/keyring/raw_keyring.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 0831dc757..55762e684 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -254,6 +254,7 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): return decryption_materials +@attr.s class RawRSAKeyring(Keyring): """Public class for Raw RSA Keyring. From e92db767afb7d92277732a227cfa64701eacb261 Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Tue, 9 Jul 2019 13:52:47 -0700 Subject: [PATCH 061/110] change KeyringTraceFlag values to bitshifted ints to match other implementations --- src/aws_encryption_sdk/identifiers.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/aws_encryption_sdk/identifiers.py b/src/aws_encryption_sdk/identifiers.py index 0bec8aacd..7f5cd3f1f 100644 --- a/src/aws_encryption_sdk/identifiers.py +++ b/src/aws_encryption_sdk/identifiers.py @@ -334,7 +334,7 @@ class KeyringTraceFlag(Enum): """KeyRing Trace actions.""" WRAPPING_KEY_GENERATED_DATA_KEY = 1 - WRAPPING_KEY_ENCRYPTED_DATA_KEY = 2 - WRAPPING_KEY_DECRYPTED_DATA_KEY = 3 - WRAPPING_KEY_SIGNED_ENC_CTX = 4 - WRAPPING_KEY_VERIFIED_ENC_CTX = 5 + WRAPPING_KEY_ENCRYPTED_DATA_KEY = 1 << 1 + WRAPPING_KEY_DECRYPTED_DATA_KEY = 1 << 2 + WRAPPING_KEY_SIGNED_ENC_CTX = 1 << 3 + WRAPPING_KEY_VERIFIED_ENC_CTX = 1 << 4 From bcd4cfec8928629c89f398351d187d962a41b0bc Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Tue, 9 Jul 2019 14:21:12 -0700 Subject: [PATCH 062/110] normalize EncryptionMaterials._encrypted_data_keys to list and encrypted_data_keys to tuple --- src/aws_encryption_sdk/materials_managers/__init__.py | 4 ++-- test/unit/test_material_managers.py | 10 +++++----- test/unit/test_material_managers_default.py | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/aws_encryption_sdk/materials_managers/__init__.py b/src/aws_encryption_sdk/materials_managers/__init__.py index a6609199a..a1947b100 100644 --- a/src/aws_encryption_sdk/materials_managers/__init__.py +++ b/src/aws_encryption_sdk/materials_managers/__init__.py @@ -243,7 +243,7 @@ def encrypted_data_keys(self): :rtype: frozenset """ - return frozenset(self._encrypted_data_keys) + return tuple(self._encrypted_data_keys) @property def is_complete(self): @@ -305,7 +305,7 @@ def add_encrypted_data_key(self, encrypted_data_key, keyring_trace): if keyring_trace.wrapping_key != encrypted_data_key.key_provider: raise InvalidKeyringTraceError("Keyring trace does not match data key encryptor.") - self._encrypted_data_keys.add(encrypted_data_key) + self._encrypted_data_keys.append(encrypted_data_key) self._keyring_trace.append(keyring_trace) def add_signing_key(self, signing_key): diff --git a/test/unit/test_material_managers.py b/test/unit/test_material_managers.py index 2f64f3c74..975e9ffda 100644 --- a/test/unit/test_material_managers.py +++ b/test/unit/test_material_managers.py @@ -68,11 +68,11 @@ "EncryptionMaterials": dict( algorithm=ALGORITHM, data_encryption_key=_DATA_KEY, - encrypted_data_keys=set([]), + encrypted_data_keys=[], encryption_context={}, signing_key=_SIGNING_KEY.key_bytes(), ), - "DecryptionMaterialsRequest": dict(algorithm=ALGORITHM, encrypted_data_keys=set([]), encryption_context={}), + "DecryptionMaterialsRequest": dict(algorithm=ALGORITHM, encrypted_data_keys=[], encryption_context={}), "DecryptionMaterials": dict( data_key=_DATA_KEY, verification_key=_VERIFICATION_KEY.key_bytes(), algorithm=ALGORITHM, encryption_context={} ), @@ -143,7 +143,7 @@ def test_encryption_materials_request_attributes_defaults(): def test_encryption_materials_defaults(): test = EncryptionMaterials( - algorithm=ALGORITHM, data_encryption_key=_DATA_KEY, encrypted_data_keys=set([]), encryption_context={} + algorithm=ALGORITHM, data_encryption_key=_DATA_KEY, encrypted_data_keys=[], encryption_context={} ) assert test.signing_key is None @@ -229,7 +229,7 @@ def test_immutable_encrypted_data_keys(): materials = EncryptionMaterials(**_VALID_KWARGS["EncryptionMaterials"]) with pytest.raises(AttributeError): - materials.encrypted_data_keys.add(42) + materials.encrypted_data_keys.append(42) def test_empty_encrypted_data_keys(): @@ -237,7 +237,7 @@ def test_empty_encrypted_data_keys(): edks = materials.encrypted_data_keys - assert isinstance(edks, frozenset) + assert isinstance(edks, tuple) assert not edks diff --git a/test/unit/test_material_managers_default.py b/test/unit/test_material_managers_default.py index 20aaa8dd6..32fdc953a 100644 --- a/test/unit/test_material_managers_default.py +++ b/test/unit/test_material_managers_default.py @@ -41,7 +41,7 @@ def patch_for_dcmm_encrypt(mocker): DefaultCryptoMaterialsManager._generate_signing_key_and_update_encryption_context.return_value = mock_signing_key mocker.patch.object(aws_encryption_sdk.materials_managers.default, "prepare_data_keys") mock_data_encryption_key = _DATA_KEY - mock_encrypted_data_keys = set([_ENCRYPTED_DATA_KEY]) + mock_encrypted_data_keys = (_ENCRYPTED_DATA_KEY,) result_pair = mock_data_encryption_key, mock_encrypted_data_keys aws_encryption_sdk.materials_managers.default.prepare_data_keys.return_value = result_pair yield result_pair, mock_signing_key @@ -165,7 +165,7 @@ def test_get_encryption_materials_primary_mk_not_in_mks(patch_for_dcmm_encrypt): cmm = build_cmm() cmm.master_key_provider.master_keys_for_encryption.return_value = ( sentinel.primary_mk, - set([sentinel.mk_a, sentinel.mk_b]), + {sentinel.mk_a, sentinel.mk_b}, ) with pytest.raises(MasterKeyProviderError) as excinfo: From be3a39197fcb4b4b0622312b24388d1659fa0043 Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Tue, 9 Jul 2019 14:21:38 -0700 Subject: [PATCH 063/110] temporarily pin pydocstyle at <4.0.0 to avoid issue breaking flake8-docstrings --- tox.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/tox.ini b/tox.ini index e13ea2cb8..3e5677ece 100644 --- a/tox.ini +++ b/tox.ini @@ -117,6 +117,7 @@ basepython = python3 deps = flake8 flake8-docstrings + pydocstyle < 4.0.0 # https://github.com/JBKahn/flake8-print/pull/30 flake8-print>=3.1.0 flake8-bugbear From 402af2c5fa7cccafec4fcb6fdb87c22148ad36b8 Mon Sep 17 00:00:00 2001 From: mattsb42-aws Date: Wed, 10 Jul 2019 12:22:51 -0700 Subject: [PATCH 064/110] temporarily cap pydocstyle at <4.0.0 for decrypt oracle --- decrypt_oracle/tox.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/decrypt_oracle/tox.ini b/decrypt_oracle/tox.ini index 60aea91c7..23a9ece86 100644 --- a/decrypt_oracle/tox.ini +++ b/decrypt_oracle/tox.ini @@ -156,6 +156,7 @@ basepython = python3 deps = flake8 flake8-docstrings + pydocstyle < 4.0.0 # https://github.com/JBKahn/flake8-print/pull/30 flake8-print>=3.1.0 commands = From be4f74cb5e636122eb21f21b9300e38e5d5a1d7a Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Fri, 12 Jul 2019 15:08:51 -0700 Subject: [PATCH 065/110] Changes to keyring trace in raw keyrings --- src/aws_encryption_sdk/keyring/raw_keyring.py | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 55762e684..13132a0b3 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -19,14 +19,13 @@ import six from aws_encryption_sdk.exceptions import EncryptKeyError -from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm +from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm, KeyringTraceFlag from aws_encryption_sdk.internal.crypto.wrapping_keys import 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.keyring.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 KeyringTrace, MasterKeyInfo, RawDataKey try: # Python 3.5.0 and 3.5.1 have incompatible typing modules from typing import Iterable # noqa pylint: disable=unused-import @@ -74,12 +73,13 @@ def on_encrypt_helper( :return: Optionally modified encryption materials. :rtype encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - # Create a keyring trace - keyring_trace = KeyringTrace(wrapping_key=key_provider, flags=set()) # Check if data key already exists if not encryption_materials.data_encryption_key: + # Create a keyring trace + keyring_trace = KeyringTrace(wrapping_key=key_provider, flags=set()) + # Generate data key plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) @@ -87,6 +87,9 @@ def on_encrypt_helper( if not plaintext_data_key: return EncryptKeyError("Unable to generate data encryption key.") + # Update Keyring Trace + keyring_trace.flags.add(KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY) + # plaintext_data_key to RawDataKey data_encryption_key = RawDataKey(key_provider=key_provider, data_key=plaintext_data_key) @@ -95,6 +98,7 @@ def on_encrypt_helper( else: plaintext_data_key = encryption_materials.data_encryption_key + keyring_trace = encryption_materials.keyring_trace # Encrypt data key encrypted_wrapped_key = wrapping_key.encrypt( @@ -109,8 +113,13 @@ def on_encrypt_helper( encrypted_wrapped_key=encrypted_wrapped_key, ) + # Update Keyring Trace + if encrypted_data_key: + keyring_trace.flags.add(KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY) + # Add encrypted data key to encryption_materials - encryption_materials.add_encrypted_data_key(encrypted_data_key, keyring_trace) + encryption_materials.add_encrypted_data_key(encrypted_data_key=encrypted_data_key, + keyring_trace=keyring_trace) return encryption_materials @@ -140,13 +149,14 @@ def on_decrypt_helper( :return: Optionally modified decryption materials. :rtype decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials """ - # Create a keyring trace - keyring_trace = KeyringTrace(wrapping_key=key_provider, flags=set()) # Check if plaintext data key exists if decryption_materials.data_key: return decryption_materials + # Create a keyring trace + keyring_trace = KeyringTrace(wrapping_key=key_provider, flags=set()) + # Wrapped EncryptedDataKey to deserialized EncryptedData encrypted_wrapped_key = deserialize_wrapped_key( wrapping_algorithm=wrapping_algorithm, wrapping_key_id=key_name, wrapped_encrypted_key=encrypted_data_key @@ -157,6 +167,7 @@ def on_decrypt_helper( plaintext_data_key = wrapping_key.decrypt( encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=decryption_materials.encryption_context ) + keyring_trace.flags.add(KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY) except Exception as error: logging.ERROR(error.__class__.__name__, ":", str(error)) return decryption_materials From c01fb904489c703f61f67442e3b9dfd43cf05c29 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Fri, 12 Jul 2019 15:46:11 -0700 Subject: [PATCH 066/110] Adding test files --- test/functional/test_f_raw_aes.py | 0 test/functional/test_f_raw_rsa.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/functional/test_f_raw_aes.py create mode 100644 test/functional/test_f_raw_rsa.py diff --git a/test/functional/test_f_raw_aes.py b/test/functional/test_f_raw_aes.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/functional/test_f_raw_rsa.py b/test/functional/test_f_raw_rsa.py new file mode 100644 index 000000000..e69de29bb From 85a014934ae3ac979c3ef2c0eb18e9d04b273da4 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Fri, 12 Jul 2019 15:48:38 -0700 Subject: [PATCH 067/110] Adding tests --- test/functional/test_f_raw_aes.py | 98 +++++++++++++++++++++++++++++++ test/functional/test_f_raw_rsa.py | 97 ++++++++++++++++++++++++++++++ 2 files changed, 195 insertions(+) diff --git a/test/functional/test_f_raw_aes.py b/test/functional/test_f_raw_aes.py index e69de29bb..a4d79eab6 100644 --- a/test/functional/test_f_raw_aes.py +++ b/test/functional/test_f_raw_aes.py @@ -0,0 +1,98 @@ +# Copyright 2019 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. +"""Functional tests for Raw AES keyring encryption decryption path.""" + +import pytest + +from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, WrappingAlgorithm +from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring, WrappingKey +from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials +from aws_encryption_sdk.structures import DataKey, EncryptedDataKey, MasterKeyInfo + +pytestmark = [pytest.mark.functional, pytest.mark.local] + +_ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"} +_PROVIDER_ID = "Random Raw Keys" +_KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" +_WRAPPING_KEY = b"\xeby-\x80A6\x15rA8\x83#,\xe4\xab\xac`\xaf\x99Z\xc1\xce\xdb\xb6\x0f\xb7\x805\xb2\x14J3" +_SIGNING_KEY = b"aws-crypto-public-key" + +_ENCRYPTION_MATERIALS = [ + EncryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + encryption_context=_ENCRYPTION_CONTEXT, + signing_key=_SIGNING_KEY, + ), + # EncryptionMaterials( + # algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + # data_encryption_key=DataKey( + # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + # data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + # ), + # encryption_context=_ENCRYPTION_CONTEXT, + # signing_key=_SIGNING_KEY, + # ), + # EncryptionMaterials( + # algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + # data_encryption_key=DataKey( + # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + # data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + # ), + # encrypted_data_keys=[ + # EncryptedDataKey( + # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + # encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" + # b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", + # ) + # ], + # encryption_context=_ENCRYPTION_CONTEXT, + # signing_key=_SIGNING_KEY, + # ), +] + + +@pytest.mark.parametrize("encryption_materials", _ENCRYPTION_MATERIALS) +def test_raw_aes_encryption_decryption(encryption_materials): + + # Initializing attributes + key_namespace = _PROVIDER_ID + key_name = _KEY_ID + _wrapping_key = WrappingKey( + wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, + wrapping_key=_WRAPPING_KEY, + wrapping_key_type=EncryptionKeyType.SYMMETRIC, + ) + _wrapping_algorithm = WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING + + # Creating an instance of a raw AES keyring + fake_raw_aes_keyring = RawAESKeyring( + key_namespace=key_namespace, + key_name=key_name, + wrapping_key=_wrapping_key, + wrapping_algorithm=_wrapping_algorithm, + ) + + # Call on_encrypt function for the keyring + encryption_materials = fake_raw_aes_keyring.on_encrypt(encryption_materials=encryption_materials) + + # Generate decryption materials + decryption_materials = DecryptionMaterials(verification_key=b"ex_verification_key") + + # Call on_decrypt function for the keyring + decryption_materials = fake_raw_aes_keyring.on_decrypt( + decryption_materials=decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys + ) + + # Check if the data keys match + assert encryption_materials.data_encryption_key == decryption_materials.data_key + diff --git a/test/functional/test_f_raw_rsa.py b/test/functional/test_f_raw_rsa.py index e69de29bb..d798d54ef 100644 --- a/test/functional/test_f_raw_rsa.py +++ b/test/functional/test_f_raw_rsa.py @@ -0,0 +1,97 @@ +# Copyright 2019 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. +"""Functional tests for Raw AES keyring encryption decryption path.""" + +import pytest + +from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, WrappingAlgorithm +from aws_encryption_sdk.keyring.raw_keyring import RawRSAKeyring, WrappingKey +from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials +from aws_encryption_sdk.structures import DataKey, EncryptedDataKey, MasterKeyInfo + +pytestmark = [pytest.mark.functional, pytest.mark.local] + +_ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"} +_PROVIDER_ID = "Random Raw Keys" +_KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" +_WRAPPING_KEY = b"\xeby-\x80A6\x15rA8\x83#,\xe4\xab\xac`\xaf\x99Z\xc1\xce\xdb\xb6\x0f\xb7\x805\xb2\x14J3" +_SIGNING_KEY = b"aws-crypto-public-key" + +_ENCRYPTION_MATERIALS = [ + EncryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + encryption_context=_ENCRYPTION_CONTEXT, + signing_key=_SIGNING_KEY, + ), + # EncryptionMaterials( + # algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + # data_encryption_key=DataKey( + # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + # data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + # ), + # encryption_context=_ENCRYPTION_CONTEXT, + # signing_key=_SIGNING_KEY, + # ), + # EncryptionMaterials( + # algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + # data_encryption_key=DataKey( + # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + # data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + # ), + # encrypted_data_keys=[ + # EncryptedDataKey( + # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + # encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" + # b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", + # ) + # ], + # encryption_context=_ENCRYPTION_CONTEXT, + # signing_key=_SIGNING_KEY, + # ), +] + + +@pytest.mark.parametrize("encryption_materials", _ENCRYPTION_MATERIALS) +def test_raw_rsa_encryption_decryption(encryption_materials): + + # Initializing attributes + key_namespace = _PROVIDER_ID + key_name = _KEY_ID + _wrapping_key = WrappingKey( + wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, + wrapping_key=_WRAPPING_KEY, + wrapping_key_type=EncryptionKeyType.PRIVATE, + ) + _wrapping_algorithm = WrappingAlgorithm.RSA_OAEP_SHA256_MGF1 + + # Creating an instance of a raw AES keyring + fake_raw_rsa_keyring = RawRSAKeyring( + key_namespace=key_namespace, + key_name=key_name, + wrapping_key=_wrapping_key, + wrapping_algorithm=_wrapping_algorithm, + ) + + # Call on_encrypt function for the keyring + encryption_materials = fake_raw_rsa_keyring.on_encrypt(encryption_materials=encryption_materials) + + # Generate decryption materials + decryption_materials = DecryptionMaterials(verification_key=b"ex_verification_key") + + # Call on_decrypt function for the keyring + decryption_materials = fake_raw_rsa_keyring.on_decrypt( + decryption_materials=decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys + ) + + # Check if the data keys match + assert encryption_materials.data_encryption_key == decryption_materials.data_key From af239f63fe6e1ccc941f7ebac190f3f22e06bb40 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Fri, 12 Jul 2019 16:26:03 -0700 Subject: [PATCH 068/110] Changed data encryption key type to RawDataKey --- test/functional/test_f_raw_aes.py | 53 +++++++++++++++---------------- test/functional/test_f_raw_rsa.py | 52 +++++++++++++++--------------- 2 files changed, 52 insertions(+), 53 deletions(-) diff --git a/test/functional/test_f_raw_aes.py b/test/functional/test_f_raw_aes.py index a4d79eab6..905c139f5 100644 --- a/test/functional/test_f_raw_aes.py +++ b/test/functional/test_f_raw_aes.py @@ -17,7 +17,7 @@ from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, WrappingAlgorithm from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring, WrappingKey from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials -from aws_encryption_sdk.structures import DataKey, EncryptedDataKey, MasterKeyInfo +from aws_encryption_sdk.structures import RawDataKey, EncryptedDataKey, MasterKeyInfo pytestmark = [pytest.mark.functional, pytest.mark.local] @@ -33,31 +33,31 @@ encryption_context=_ENCRYPTION_CONTEXT, signing_key=_SIGNING_KEY, ), - # EncryptionMaterials( - # algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - # data_encryption_key=DataKey( - # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - # data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - # ), - # encryption_context=_ENCRYPTION_CONTEXT, - # signing_key=_SIGNING_KEY, - # ), - # EncryptionMaterials( - # algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - # data_encryption_key=DataKey( - # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - # data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - # ), - # encrypted_data_keys=[ - # EncryptedDataKey( - # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - # encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" - # b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", - # ) - # ], - # encryption_context=_ENCRYPTION_CONTEXT, - # signing_key=_SIGNING_KEY, - # ), + EncryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + data_encryption_key=RawDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + ), + encryption_context=_ENCRYPTION_CONTEXT, + signing_key=_SIGNING_KEY, + ), + EncryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + data_encryption_key=RawDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + ), + encrypted_data_keys=[ + EncryptedDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" + b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", + ) + ], + encryption_context=_ENCRYPTION_CONTEXT, + signing_key=_SIGNING_KEY, + ), ] @@ -95,4 +95,3 @@ def test_raw_aes_encryption_decryption(encryption_materials): # Check if the data keys match assert encryption_materials.data_encryption_key == decryption_materials.data_key - diff --git a/test/functional/test_f_raw_rsa.py b/test/functional/test_f_raw_rsa.py index d798d54ef..a5fbbce7e 100644 --- a/test/functional/test_f_raw_rsa.py +++ b/test/functional/test_f_raw_rsa.py @@ -17,7 +17,7 @@ from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, WrappingAlgorithm from aws_encryption_sdk.keyring.raw_keyring import RawRSAKeyring, WrappingKey from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials -from aws_encryption_sdk.structures import DataKey, EncryptedDataKey, MasterKeyInfo +from aws_encryption_sdk.structures import RawDataKey, EncryptedDataKey, MasterKeyInfo pytestmark = [pytest.mark.functional, pytest.mark.local] @@ -33,31 +33,31 @@ encryption_context=_ENCRYPTION_CONTEXT, signing_key=_SIGNING_KEY, ), - # EncryptionMaterials( - # algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - # data_encryption_key=DataKey( - # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - # data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - # ), - # encryption_context=_ENCRYPTION_CONTEXT, - # signing_key=_SIGNING_KEY, - # ), - # EncryptionMaterials( - # algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - # data_encryption_key=DataKey( - # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - # data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - # ), - # encrypted_data_keys=[ - # EncryptedDataKey( - # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - # encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" - # b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", - # ) - # ], - # encryption_context=_ENCRYPTION_CONTEXT, - # signing_key=_SIGNING_KEY, - # ), + EncryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + data_encryption_key=RawDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + ), + encryption_context=_ENCRYPTION_CONTEXT, + signing_key=_SIGNING_KEY, + ), + EncryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + data_encryption_key=RawDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + ), + encrypted_data_keys=[ + EncryptedDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" + b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", + ) + ], + encryption_context=_ENCRYPTION_CONTEXT, + signing_key=_SIGNING_KEY, + ), ] From 1a4942712934ff9ebf358578164c4de2dd451d16 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Sat, 13 Jul 2019 20:55:42 -0700 Subject: [PATCH 069/110] Added keyring trace to pytest encryption materials --- src/aws_encryption_sdk/keyring/raw_keyring.py | 15 ++--- .../materials_managers/__init__.py | 2 +- test/functional/test_f_raw_aes.py | 59 ++++++++++--------- test/functional/test_f_raw_rsa.py | 59 ++++++++++--------- 4 files changed, 71 insertions(+), 64 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index a02b65608..caa24685e 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -78,9 +78,6 @@ def on_encrypt_helper( # Check if data key already exists if not encryption_materials.data_encryption_key: - # Create a keyring trace - keyring_trace = KeyringTrace(wrapping_key=key_provider, flags=set()) - # Generate data key plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) @@ -88,8 +85,9 @@ def on_encrypt_helper( if not plaintext_data_key: raise EncryptKeyError("Unable to generate data encryption key.") - # Update Keyring Trace - keyring_trace.flags.add(KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY) + # Create a keyring trace + keyring_trace = KeyringTrace(wrapping_key=key_provider, + flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}) # plaintext_data_key to RawDataKey data_encryption_key = RawDataKey(key_provider=key_provider, data_key=plaintext_data_key) @@ -158,9 +156,6 @@ def on_decrypt_helper( if decryption_materials.data_key: return decryption_materials - # Create a keyring trace - keyring_trace = KeyringTrace(wrapping_key=key_provider, flags=set()) - # Wrapped EncryptedDataKey to deserialized EncryptedData encrypted_wrapped_key = deserialize_wrapped_key( wrapping_algorithm=wrapping_algorithm, wrapping_key_id=key_name, wrapped_encrypted_key=encrypted_data_key @@ -171,7 +166,9 @@ def on_decrypt_helper( plaintext_data_key = wrapping_key.decrypt( encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=decryption_materials.encryption_context ) - keyring_trace.flags.add(KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY) + # Create a keyring trace + keyring_trace = KeyringTrace(wrapping_key=encrypted_wrapped_key.key_provider, + flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY}) except Exception as error: logging.ERROR(error.__class__.__name__, ":", str(error)) diff --git a/src/aws_encryption_sdk/materials_managers/__init__.py b/src/aws_encryption_sdk/materials_managers/__init__.py index a1947b100..0c4459aca 100644 --- a/src/aws_encryption_sdk/materials_managers/__init__.py +++ b/src/aws_encryption_sdk/materials_managers/__init__.py @@ -191,7 +191,7 @@ class EncryptionMaterials(CryptographicMaterials): Most parameters are now optional. :param Algorithm algorithm: Algorithm to use for encrypting message - :param DataKey data_encryption_key: Plaintext data key to use for encrypting message (optional) + :param RawDataKey data_encryption_key: Plaintext data key to use for encrypting message (optional) :param encrypted_data_keys: List of encrypted data keys (optional) :type encrypted_data_keys: list of :class:`EncryptedDataKey` :param dict encryption_context: Encryption context tied to `encrypted_data_keys` diff --git a/test/functional/test_f_raw_aes.py b/test/functional/test_f_raw_aes.py index 905c139f5..ca58112ab 100644 --- a/test/functional/test_f_raw_aes.py +++ b/test/functional/test_f_raw_aes.py @@ -14,10 +14,10 @@ import pytest -from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, WrappingAlgorithm +from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, WrappingAlgorithm, KeyringTraceFlag from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring, WrappingKey from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials -from aws_encryption_sdk.structures import RawDataKey, EncryptedDataKey, MasterKeyInfo +from aws_encryption_sdk.structures import RawDataKey, EncryptedDataKey, MasterKeyInfo, KeyringTrace pytestmark = [pytest.mark.functional, pytest.mark.local] @@ -33,31 +33,36 @@ encryption_context=_ENCRYPTION_CONTEXT, signing_key=_SIGNING_KEY, ), - EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - ), - EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encrypted_data_keys=[ - EncryptedDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" - b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", - ) - ], - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - ), + # EncryptionMaterials( + # algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + # data_encryption_key=RawDataKey( + # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + # data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + # ), + # encryption_context=_ENCRYPTION_CONTEXT, + # signing_key=_SIGNING_KEY, + # keyring_trace=KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + # flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}) + # ), + # EncryptionMaterials( + # algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + # data_encryption_key=RawDataKey( + # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + # data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + # ), + # encrypted_data_keys=[ + # EncryptedDataKey( + # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + # encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" + # b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", + # ) + # ], + # encryption_context=_ENCRYPTION_CONTEXT, + # signing_key=_SIGNING_KEY, + # keyring_trace=KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + # flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, + # KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}) + # ), ] diff --git a/test/functional/test_f_raw_rsa.py b/test/functional/test_f_raw_rsa.py index a5fbbce7e..b450e350d 100644 --- a/test/functional/test_f_raw_rsa.py +++ b/test/functional/test_f_raw_rsa.py @@ -14,10 +14,10 @@ import pytest -from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, WrappingAlgorithm +from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, WrappingAlgorithm, KeyringTraceFlag from aws_encryption_sdk.keyring.raw_keyring import RawRSAKeyring, WrappingKey from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials -from aws_encryption_sdk.structures import RawDataKey, EncryptedDataKey, MasterKeyInfo +from aws_encryption_sdk.structures import RawDataKey, EncryptedDataKey, MasterKeyInfo, KeyringTrace pytestmark = [pytest.mark.functional, pytest.mark.local] @@ -33,31 +33,36 @@ encryption_context=_ENCRYPTION_CONTEXT, signing_key=_SIGNING_KEY, ), - EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - ), - EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encrypted_data_keys=[ - EncryptedDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" - b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", - ) - ], - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - ), + # EncryptionMaterials( + # algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + # data_encryption_key=RawDataKey( + # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + # data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + # ), + # encryption_context=_ENCRYPTION_CONTEXT, + # signing_key=_SIGNING_KEY, + # keyring_trace=KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + # flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}) + # ), + # EncryptionMaterials( + # algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + # data_encryption_key=RawDataKey( + # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + # data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + # ), + # encrypted_data_keys=[ + # EncryptedDataKey( + # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + # encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" + # b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", + # ) + # ], + # encryption_context=_ENCRYPTION_CONTEXT, + # signing_key=_SIGNING_KEY, + # keyring_trace=KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + # flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, + # KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}) + # ), ] From ec1d8b5aa0469114dc2dc391f4317522ba0f2ed4 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Mon, 15 Jul 2019 10:48:05 -0700 Subject: [PATCH 070/110] Changed value of keyring_trace.wrapping_key --- src/aws_encryption_sdk/keyring/raw_keyring.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index caa24685e..4bdef0d7a 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -114,6 +114,7 @@ def on_encrypt_helper( # Update Keyring Trace if encrypted_data_key: + keyring_trace.wrapping_key = encrypted_data_key.key_provider keyring_trace.flags.add(KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY) # Add encrypted data key to encryption_materials @@ -166,14 +167,16 @@ def on_decrypt_helper( plaintext_data_key = wrapping_key.decrypt( encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=decryption_materials.encryption_context ) - # Create a keyring trace - keyring_trace = KeyringTrace(wrapping_key=encrypted_wrapped_key.key_provider, - flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY}) except Exception as error: logging.ERROR(error.__class__.__name__, ":", str(error)) return decryption_materials + if plaintext_data_key: + # Create a keyring trace + keyring_trace = KeyringTrace(wrapping_key=key_provider, + flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY}) + # Update decryption materials data_encryption_key = RawDataKey( key_provider=MasterKeyInfo(provider_id=key_provider.provider_id, key_info=key_name), data_key=plaintext_data_key From 5ff39d64c1848cdc449d3fec745214fedc81ea75 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Mon, 15 Jul 2019 13:23:59 -0700 Subject: [PATCH 071/110] Few changes to match new API --- src/aws_encryption_sdk/keyring/raw_keyring.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 4bdef0d7a..fbe1d84d1 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -154,7 +154,7 @@ def on_decrypt_helper( """ # Check if plaintext data key exists - if decryption_materials.data_key: + if decryption_materials.data_encryption_key: return decryption_materials # Wrapped EncryptedDataKey to deserialized EncryptedData @@ -177,11 +177,12 @@ def on_decrypt_helper( keyring_trace = KeyringTrace(wrapping_key=key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY}) - # Update decryption materials - data_encryption_key = RawDataKey( - key_provider=MasterKeyInfo(provider_id=key_provider.provider_id, key_info=key_name), data_key=plaintext_data_key - ) - decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) + # Update decryption materials + data_encryption_key = RawDataKey( + key_provider=MasterKeyInfo(provider_id=key_provider.provider_id, key_info=key_name), + data_key=plaintext_data_key + ) + decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) return decryption_materials From 64298a704971a3df6f11cfbcaf9d45943e62aa5e Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Mon, 15 Jul 2019 14:52:40 -0700 Subject: [PATCH 072/110] Tox errors --- src/aws_encryption_sdk/keyring/raw_keyring.py | 24 +++++++++---------- test/functional/test_f_raw_aes.py | 4 ++-- test/functional/test_f_raw_rsa.py | 4 ++-- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index fbe1d84d1..8233cba28 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -19,12 +19,12 @@ import six from aws_encryption_sdk.exceptions import EncryptKeyError -from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm, KeyringTraceFlag +from aws_encryption_sdk.identifiers import EncryptionKeyType, KeyringTraceFlag, WrappingAlgorithm from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey from aws_encryption_sdk.internal.formatting.deserialize import deserialize_wrapped_key -from aws_encryption_sdk.keyring.base import Keyring 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.keyring.base import Keyring from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey @@ -74,7 +74,6 @@ def on_encrypt_helper( :return: Optionally modified encryption materials. :rtype encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - # Check if data key already exists if not encryption_materials.data_encryption_key: @@ -86,8 +85,9 @@ def on_encrypt_helper( raise EncryptKeyError("Unable to generate data encryption key.") # Create a keyring trace - keyring_trace = KeyringTrace(wrapping_key=key_provider, - flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}) + keyring_trace = KeyringTrace( + wrapping_key=key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY} + ) # plaintext_data_key to RawDataKey data_encryption_key = RawDataKey(key_provider=key_provider, data_key=plaintext_data_key) @@ -118,8 +118,7 @@ def on_encrypt_helper( keyring_trace.flags.add(KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY) # Add encrypted data key to encryption_materials - encryption_materials.add_encrypted_data_key(encrypted_data_key=encrypted_data_key, - keyring_trace=keyring_trace) + encryption_materials.add_encrypted_data_key(encrypted_data_key=encrypted_data_key, keyring_trace=keyring_trace) # Add encrypted data key to encryption_materials encryption_materials.add_encrypted_data_key(encrypted_data_key, keyring_trace) @@ -152,7 +151,6 @@ def on_decrypt_helper( :return: Optionally modified decryption materials. :rtype decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials """ - # Check if plaintext data key exists if decryption_materials.data_encryption_key: return decryption_materials @@ -169,18 +167,20 @@ def on_decrypt_helper( ) except Exception as error: - logging.ERROR(error.__class__.__name__, ":", str(error)) + logger = logging.getLogger() + logger.error(error.__class__.__name__, ":", str(error)) return decryption_materials if plaintext_data_key: # Create a keyring trace - keyring_trace = KeyringTrace(wrapping_key=key_provider, - flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY}) + keyring_trace = KeyringTrace( + wrapping_key=key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} + ) # Update decryption materials data_encryption_key = RawDataKey( key_provider=MasterKeyInfo(provider_id=key_provider.provider_id, key_info=key_name), - data_key=plaintext_data_key + data_key=plaintext_data_key, ) decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) diff --git a/test/functional/test_f_raw_aes.py b/test/functional/test_f_raw_aes.py index ca58112ab..5764c07e5 100644 --- a/test/functional/test_f_raw_aes.py +++ b/test/functional/test_f_raw_aes.py @@ -14,10 +14,10 @@ import pytest -from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, WrappingAlgorithm, KeyringTraceFlag +from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, KeyringTraceFlag, WrappingAlgorithm from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring, WrappingKey from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials -from aws_encryption_sdk.structures import RawDataKey, EncryptedDataKey, MasterKeyInfo, KeyringTrace +from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey pytestmark = [pytest.mark.functional, pytest.mark.local] diff --git a/test/functional/test_f_raw_rsa.py b/test/functional/test_f_raw_rsa.py index b450e350d..0fefb2fba 100644 --- a/test/functional/test_f_raw_rsa.py +++ b/test/functional/test_f_raw_rsa.py @@ -14,10 +14,10 @@ import pytest -from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, WrappingAlgorithm, KeyringTraceFlag +from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, KeyringTraceFlag, WrappingAlgorithm from aws_encryption_sdk.keyring.raw_keyring import RawRSAKeyring, WrappingKey from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials -from aws_encryption_sdk.structures import RawDataKey, EncryptedDataKey, MasterKeyInfo, KeyringTrace +from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey pytestmark = [pytest.mark.functional, pytest.mark.local] From cc5aa44d6e957eb0affa9d82f8def2d53832108a Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 16 Jul 2019 13:49:42 -0700 Subject: [PATCH 073/110] Functional tests pass --- src/aws_encryption_sdk/keyring/raw_keyring.py | 17 ++- .../materials_managers/__init__.py | 2 +- test/functional/test_f_raw_aes.py | 85 +++++++------ test/functional/test_f_raw_rsa.py | 119 ++++++++++++------ 4 files changed, 137 insertions(+), 86 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 8233cba28..e3e53d73e 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -86,7 +86,8 @@ def on_encrypt_helper( # Create a keyring trace keyring_trace = KeyringTrace( - wrapping_key=key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY} + wrapping_key=key_provider, + flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY} ) # plaintext_data_key to RawDataKey @@ -96,8 +97,7 @@ def on_encrypt_helper( encryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) else: - plaintext_data_key = encryption_materials.data_encryption_key - keyring_trace = encryption_materials.keyring_trace + plaintext_data_key = encryption_materials.data_encryption_key.data_key # Encrypt data key encrypted_wrapped_key = wrapping_key.encrypt( @@ -114,14 +114,11 @@ def on_encrypt_helper( # Update Keyring Trace if encrypted_data_key: - keyring_trace.wrapping_key = encrypted_data_key.key_provider - keyring_trace.flags.add(KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY) + keyring_trace = KeyringTrace(wrapping_key=encrypted_data_key.key_provider, + flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}) - # Add encrypted data key to encryption_materials - encryption_materials.add_encrypted_data_key(encrypted_data_key=encrypted_data_key, keyring_trace=keyring_trace) - - # Add encrypted data key to encryption_materials - encryption_materials.add_encrypted_data_key(encrypted_data_key, keyring_trace) + # Add encrypted data key to encryption_materials + encryption_materials.add_encrypted_data_key(encrypted_data_key=encrypted_data_key, keyring_trace=keyring_trace) return encryption_materials diff --git a/src/aws_encryption_sdk/materials_managers/__init__.py b/src/aws_encryption_sdk/materials_managers/__init__.py index 0c4459aca..0a6dcd2f0 100644 --- a/src/aws_encryption_sdk/materials_managers/__init__.py +++ b/src/aws_encryption_sdk/materials_managers/__init__.py @@ -370,7 +370,7 @@ class DecryptionMaterials(CryptographicMaterials): All parameters are now optional. :param Algorithm algorithm: Algorithm to use for encrypting message (optional) - :param DataKey data_encryption_key: Plaintext data key to use for encrypting message (optional) + :param RawDataKey data_encryption_key: Plaintext data key to use for encrypting message (optional) :param dict encryption_context: Encryption context tied to `encrypted_data_keys` (optional) :param bytes verification_key: Raw signature verification key (optional) :param keyring_trace: Any KeyRing trace entries (optional) diff --git a/test/functional/test_f_raw_aes.py b/test/functional/test_f_raw_aes.py index 5764c07e5..9a92e5dea 100644 --- a/test/functional/test_f_raw_aes.py +++ b/test/functional/test_f_raw_aes.py @@ -14,7 +14,7 @@ import pytest -from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, KeyringTraceFlag, WrappingAlgorithm +from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, WrappingAlgorithm, KeyringTraceFlag from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring, WrappingKey from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey @@ -33,41 +33,49 @@ encryption_context=_ENCRYPTION_CONTEXT, signing_key=_SIGNING_KEY, ), - # EncryptionMaterials( - # algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - # data_encryption_key=RawDataKey( - # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - # data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - # ), - # encryption_context=_ENCRYPTION_CONTEXT, - # signing_key=_SIGNING_KEY, - # keyring_trace=KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - # flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}) - # ), - # EncryptionMaterials( - # algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - # data_encryption_key=RawDataKey( - # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - # data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - # ), - # encrypted_data_keys=[ - # EncryptedDataKey( - # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - # encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" - # b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", - # ) - # ], - # encryption_context=_ENCRYPTION_CONTEXT, - # signing_key=_SIGNING_KEY, - # keyring_trace=KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - # flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, - # KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}) - # ), + EncryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + data_encryption_key=RawDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + ), + encryption_context=_ENCRYPTION_CONTEXT, + signing_key=_SIGNING_KEY, + keyring_trace=[KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, + key_info=_KEY_ID), + flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY})] + ), + EncryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + data_encryption_key=RawDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + ), + encrypted_data_keys=[ + EncryptedDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" + b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", + ) + ], + encryption_context=_ENCRYPTION_CONTEXT, + signing_key=_SIGNING_KEY, + keyring_trace=[ + KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, + key_info=_KEY_ID), + flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, + KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}), + # KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, + # key_info=_KEY_ID), + # flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY} + # ) + ] + ), ] -@pytest.mark.parametrize("encryption_materials", _ENCRYPTION_MATERIALS) -def test_raw_aes_encryption_decryption(encryption_materials): +@pytest.mark.parametrize("encryption_materials_samples", _ENCRYPTION_MATERIALS) +def test_raw_aes_encryption_decryption(encryption_materials_samples): # Initializing attributes key_namespace = _PROVIDER_ID @@ -88,15 +96,18 @@ def test_raw_aes_encryption_decryption(encryption_materials): ) # Call on_encrypt function for the keyring - encryption_materials = fake_raw_aes_keyring.on_encrypt(encryption_materials=encryption_materials) + encryption_materials = fake_raw_aes_keyring.on_encrypt(encryption_materials=encryption_materials_samples) # Generate decryption materials - decryption_materials = DecryptionMaterials(verification_key=b"ex_verification_key") + decryption_materials = DecryptionMaterials(algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + verification_key=b"ex_verification_key") # Call on_decrypt function for the keyring decryption_materials = fake_raw_aes_keyring.on_decrypt( decryption_materials=decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys ) - # Check if the data keys match - assert encryption_materials.data_encryption_key == decryption_materials.data_key + if decryption_materials.data_encryption_key: + # Check if the data keys match + assert encryption_materials.data_encryption_key == decryption_materials.data_encryption_key + return diff --git a/test/functional/test_f_raw_rsa.py b/test/functional/test_f_raw_rsa.py index 0fefb2fba..5d3900741 100644 --- a/test/functional/test_f_raw_rsa.py +++ b/test/functional/test_f_raw_rsa.py @@ -13,8 +13,10 @@ """Functional tests for Raw AES keyring encryption decryption path.""" import pytest +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives.asymmetric import rsa -from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, KeyringTraceFlag, WrappingAlgorithm +from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, WrappingAlgorithm, KeyringTraceFlag from aws_encryption_sdk.keyring.raw_keyring import RawRSAKeyring, WrappingKey from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey @@ -24,7 +26,37 @@ _ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"} _PROVIDER_ID = "Random Raw Keys" _KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" -_WRAPPING_KEY = b"\xeby-\x80A6\x15rA8\x83#,\xe4\xab\xac`\xaf\x99Z\xc1\xce\xdb\xb6\x0f\xb7\x805\xb2\x14J3" +pem = rsa.generate_private_key(public_exponent=65537, + key_size=2048, + backend=default_backend()) +_WRAPPING_KEY = ( + b"-----BEGIN RSA PRIVATE KEY-----\n" + b"MIIEowIBAAKCAQEAo8uCyhiO4JUGZV+rtNq5DBA9Lm4xkw5kTA3v6EPybs8bVXL2\n" + b"ZE6jkbo+xT4Jg/bKzUpnp1fE+T1ruGPtsPdoEmhY/P64LDNIs3sRq5U4QV9IETU1\n" + b"vIcbNNkgGhRjV8J87YNY0tV0H7tuWuZRpqnS+gjV6V9lUMkbvjMCc5IBqQc3heut\n" + b"/+fH4JwpGlGxOVXI8QAapnSy1XpCr3+PT29kydVJnIMuAoFrurojRpOQbOuVvhtA\n" + b"gARhst1Ji4nfROGYkj6eZhvkz2Bkud4/+3lGvVU5LO1vD8oY7WoGtpin3h50VcWe\n" + b"aBT4kejx4s9/G9C4R24lTH09J9HO2UUsuCqZYQIDAQABAoIBAQCfC90bCk+qaWqF\n" + b"gymC+qOWwCn4bM28gswHQb1D5r6AtKBRD8mKywVvWs7azguFVV3Fi8sspkBA2FBC\n" + b"At5p6ULoJOTL/TauzLl6djVJTCMM701WUDm2r+ZOIctXJ5bzP4n5Q4I7b0NMEL7u\n" + b"ixib4elYGr5D1vrVQAKtZHCr8gmkqyx8Mz7wkJepzBP9EeVzETCHsmiQDd5WYlO1\n" + b"C2IQYgw6MJzgM4entJ0V/GPytkodblGY95ORVK7ZhyNtda+r5BZ6/jeMW+hA3VoK\n" + b"tHSWjHt06ueVCCieZIATmYzBNt+zEz5UA2l7ksg3eWfVORJQS7a6Ef4VvbJLM9Ca\n" + b"m1kdsjelAoGBANKgvRf39i3bSuvm5VoyJuqinSb/23IH3Zo7XOZ5G164vh49E9Cq\n" + b"dOXXVxox74ppj/kbGUoOk+AvaB48zzfzNvac0a7lRHExykPH2kVrI/NwH/1OcT/x\n" + b"2e2DnFYocXcb4gbdZQ+m6X3zkxOYcONRzPVW1uMrFTWHcJveMUm4PGx7AoGBAMcU\n" + b"IRvrT6ye5se0s27gHnPweV+3xjsNtXZcK82N7duXyHmNjxrwOAv0SOhUmTkRXArM\n" + b"6aN5D8vyZBSWma2TgUKwpQYFTI+4Sp7sdkkyojGAEixJ+c5TZJNxZFrUe0FwAoic\n" + b"c2kb7ntaiEj5G+qHvykJJro5hy6uLnjiMVbAiJDTAoGAKb67241EmHAXGEwp9sdr\n" + b"2SMjnIAnQSF39UKAthkYqJxa6elXDQtLoeYdGE7/V+J2K3wIdhoPiuY6b4vD0iX9\n" + b"JcGM+WntN7YTjX2FsC588JmvbWfnoDHR7HYiPR1E58N597xXdFOzgUgORVr4PMWQ\n" + b"pqtwaZO3X2WZlvrhr+e46hMCgYBfdIdrm6jYXFjL6RkgUNZJQUTxYGzsY+ZemlNm\n" + b"fGdQo7a8kePMRuKY2MkcnXPaqTg49YgRmjq4z8CtHokRcWjJUWnPOTs8rmEZUshk\n" + b"0KJ0mbQdCFt/Uv0mtXgpFTkEZ3DPkDTGcV4oR4CRfOCl0/EU/A5VvL/U4i/mRo7h\n" + b"ye+xgQKBgD58b+9z+PR5LAJm1tZHIwb4tnyczP28PzwknxFd2qylR4ZNgvAUqGtU\n" + b"xvpUDpzMioz6zUH9YV43YNtt+5Xnzkqj+u9Mr27/H2v9XPwORGfwQ5XPwRJz/2oC\n" + b"EnPmP1SZoY9lXKUpQXHXSpDZ2rE2Klt3RHMUMHt8Zpy36E8Vwx8o\n" + b"-----END RSA PRIVATE KEY-----\n") _SIGNING_KEY = b"aws-crypto-public-key" _ENCRYPTION_MATERIALS = [ @@ -33,41 +65,49 @@ encryption_context=_ENCRYPTION_CONTEXT, signing_key=_SIGNING_KEY, ), - # EncryptionMaterials( - # algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - # data_encryption_key=RawDataKey( - # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - # data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - # ), - # encryption_context=_ENCRYPTION_CONTEXT, - # signing_key=_SIGNING_KEY, - # keyring_trace=KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - # flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}) - # ), - # EncryptionMaterials( - # algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - # data_encryption_key=RawDataKey( - # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - # data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - # ), - # encrypted_data_keys=[ - # EncryptedDataKey( - # key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - # encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" - # b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", - # ) - # ], - # encryption_context=_ENCRYPTION_CONTEXT, - # signing_key=_SIGNING_KEY, - # keyring_trace=KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - # flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, - # KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}) - # ), + EncryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + data_encryption_key=RawDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + ), + encryption_context=_ENCRYPTION_CONTEXT, + signing_key=_SIGNING_KEY, + keyring_trace=[KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, + key_info=_KEY_ID), + flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY})] + ), + EncryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + data_encryption_key=RawDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + ), + encrypted_data_keys=[ + EncryptedDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" + b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", + ) + ], + encryption_context=_ENCRYPTION_CONTEXT, + signing_key=_SIGNING_KEY, + keyring_trace=[ + KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, + key_info=_KEY_ID), + flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, + KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}), + # KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, + # key_info=_KEY_ID), + # flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY} + # ) + ] + ), ] -@pytest.mark.parametrize("encryption_materials", _ENCRYPTION_MATERIALS) -def test_raw_rsa_encryption_decryption(encryption_materials): +@pytest.mark.parametrize("encryption_materials_samples", _ENCRYPTION_MATERIALS) +def test_raw_rsa_encryption_decryption(encryption_materials_samples): # Initializing attributes key_namespace = _PROVIDER_ID @@ -88,15 +128,18 @@ def test_raw_rsa_encryption_decryption(encryption_materials): ) # Call on_encrypt function for the keyring - encryption_materials = fake_raw_rsa_keyring.on_encrypt(encryption_materials=encryption_materials) + encryption_materials = fake_raw_rsa_keyring.on_encrypt(encryption_materials=encryption_materials_samples) # Generate decryption materials - decryption_materials = DecryptionMaterials(verification_key=b"ex_verification_key") + decryption_materials = DecryptionMaterials(algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + verification_key=b"ex_verification_key") # Call on_decrypt function for the keyring decryption_materials = fake_raw_rsa_keyring.on_decrypt( decryption_materials=decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys ) - # Check if the data keys match - assert encryption_materials.data_encryption_key == decryption_materials.data_key + if decryption_materials.data_encryption_key: + # Check if the data keys match + assert encryption_materials.data_encryption_key == decryption_materials.data_encryption_key + return From 7d896d14a9941c5e09196fbd39a9b184b17c52a8 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 16 Jul 2019 13:50:42 -0700 Subject: [PATCH 074/110] Formatting errors corrected and functional tests pass --- src/aws_encryption_sdk/keyring/raw_keyring.py | 8 +- test/functional/test_f_raw_aes.py | 29 +++--- test/functional/test_f_raw_rsa.py | 88 ++++++++++--------- 3 files changed, 69 insertions(+), 56 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index e3e53d73e..30ec3968e 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -86,8 +86,7 @@ def on_encrypt_helper( # Create a keyring trace keyring_trace = KeyringTrace( - wrapping_key=key_provider, - flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY} + wrapping_key=key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY} ) # plaintext_data_key to RawDataKey @@ -114,8 +113,9 @@ def on_encrypt_helper( # Update Keyring Trace if encrypted_data_key: - keyring_trace = KeyringTrace(wrapping_key=encrypted_data_key.key_provider, - flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}) + keyring_trace = KeyringTrace( + wrapping_key=encrypted_data_key.key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY} + ) # Add encrypted data key to encryption_materials encryption_materials.add_encrypted_data_key(encrypted_data_key=encrypted_data_key, keyring_trace=keyring_trace) diff --git a/test/functional/test_f_raw_aes.py b/test/functional/test_f_raw_aes.py index 9a92e5dea..770063cfb 100644 --- a/test/functional/test_f_raw_aes.py +++ b/test/functional/test_f_raw_aes.py @@ -14,7 +14,7 @@ import pytest -from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, WrappingAlgorithm, KeyringTraceFlag +from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, KeyringTraceFlag, WrappingAlgorithm from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring, WrappingKey from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey @@ -41,9 +41,12 @@ ), encryption_context=_ENCRYPTION_CONTEXT, signing_key=_SIGNING_KEY, - keyring_trace=[KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, - key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY})] + keyring_trace=[ + KeyringTrace( + wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}, + ) + ], ), EncryptionMaterials( algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, @@ -61,15 +64,18 @@ encryption_context=_ENCRYPTION_CONTEXT, signing_key=_SIGNING_KEY, keyring_trace=[ - KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, - key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, - KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}), + KeyringTrace( + wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + flags={ + KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, + KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY, + }, + ), # KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, # key_info=_KEY_ID), # flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY} # ) - ] + ], ), ] @@ -99,8 +105,9 @@ def test_raw_aes_encryption_decryption(encryption_materials_samples): encryption_materials = fake_raw_aes_keyring.on_encrypt(encryption_materials=encryption_materials_samples) # Generate decryption materials - decryption_materials = DecryptionMaterials(algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - verification_key=b"ex_verification_key") + decryption_materials = DecryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, verification_key=b"ex_verification_key" + ) # Call on_decrypt function for the keyring decryption_materials = fake_raw_aes_keyring.on_decrypt( diff --git a/test/functional/test_f_raw_rsa.py b/test/functional/test_f_raw_rsa.py index 5d3900741..ea3f20441 100644 --- a/test/functional/test_f_raw_rsa.py +++ b/test/functional/test_f_raw_rsa.py @@ -16,7 +16,7 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import rsa -from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, WrappingAlgorithm, KeyringTraceFlag +from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, KeyringTraceFlag, WrappingAlgorithm from aws_encryption_sdk.keyring.raw_keyring import RawRSAKeyring, WrappingKey from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey @@ -26,37 +26,36 @@ _ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"} _PROVIDER_ID = "Random Raw Keys" _KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" -pem = rsa.generate_private_key(public_exponent=65537, - key_size=2048, - backend=default_backend()) +pem = rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend()) _WRAPPING_KEY = ( - b"-----BEGIN RSA PRIVATE KEY-----\n" - b"MIIEowIBAAKCAQEAo8uCyhiO4JUGZV+rtNq5DBA9Lm4xkw5kTA3v6EPybs8bVXL2\n" - b"ZE6jkbo+xT4Jg/bKzUpnp1fE+T1ruGPtsPdoEmhY/P64LDNIs3sRq5U4QV9IETU1\n" - b"vIcbNNkgGhRjV8J87YNY0tV0H7tuWuZRpqnS+gjV6V9lUMkbvjMCc5IBqQc3heut\n" - b"/+fH4JwpGlGxOVXI8QAapnSy1XpCr3+PT29kydVJnIMuAoFrurojRpOQbOuVvhtA\n" - b"gARhst1Ji4nfROGYkj6eZhvkz2Bkud4/+3lGvVU5LO1vD8oY7WoGtpin3h50VcWe\n" - b"aBT4kejx4s9/G9C4R24lTH09J9HO2UUsuCqZYQIDAQABAoIBAQCfC90bCk+qaWqF\n" - b"gymC+qOWwCn4bM28gswHQb1D5r6AtKBRD8mKywVvWs7azguFVV3Fi8sspkBA2FBC\n" - b"At5p6ULoJOTL/TauzLl6djVJTCMM701WUDm2r+ZOIctXJ5bzP4n5Q4I7b0NMEL7u\n" - b"ixib4elYGr5D1vrVQAKtZHCr8gmkqyx8Mz7wkJepzBP9EeVzETCHsmiQDd5WYlO1\n" - b"C2IQYgw6MJzgM4entJ0V/GPytkodblGY95ORVK7ZhyNtda+r5BZ6/jeMW+hA3VoK\n" - b"tHSWjHt06ueVCCieZIATmYzBNt+zEz5UA2l7ksg3eWfVORJQS7a6Ef4VvbJLM9Ca\n" - b"m1kdsjelAoGBANKgvRf39i3bSuvm5VoyJuqinSb/23IH3Zo7XOZ5G164vh49E9Cq\n" - b"dOXXVxox74ppj/kbGUoOk+AvaB48zzfzNvac0a7lRHExykPH2kVrI/NwH/1OcT/x\n" - b"2e2DnFYocXcb4gbdZQ+m6X3zkxOYcONRzPVW1uMrFTWHcJveMUm4PGx7AoGBAMcU\n" - b"IRvrT6ye5se0s27gHnPweV+3xjsNtXZcK82N7duXyHmNjxrwOAv0SOhUmTkRXArM\n" - b"6aN5D8vyZBSWma2TgUKwpQYFTI+4Sp7sdkkyojGAEixJ+c5TZJNxZFrUe0FwAoic\n" - b"c2kb7ntaiEj5G+qHvykJJro5hy6uLnjiMVbAiJDTAoGAKb67241EmHAXGEwp9sdr\n" - b"2SMjnIAnQSF39UKAthkYqJxa6elXDQtLoeYdGE7/V+J2K3wIdhoPiuY6b4vD0iX9\n" - b"JcGM+WntN7YTjX2FsC588JmvbWfnoDHR7HYiPR1E58N597xXdFOzgUgORVr4PMWQ\n" - b"pqtwaZO3X2WZlvrhr+e46hMCgYBfdIdrm6jYXFjL6RkgUNZJQUTxYGzsY+ZemlNm\n" - b"fGdQo7a8kePMRuKY2MkcnXPaqTg49YgRmjq4z8CtHokRcWjJUWnPOTs8rmEZUshk\n" - b"0KJ0mbQdCFt/Uv0mtXgpFTkEZ3DPkDTGcV4oR4CRfOCl0/EU/A5VvL/U4i/mRo7h\n" - b"ye+xgQKBgD58b+9z+PR5LAJm1tZHIwb4tnyczP28PzwknxFd2qylR4ZNgvAUqGtU\n" - b"xvpUDpzMioz6zUH9YV43YNtt+5Xnzkqj+u9Mr27/H2v9XPwORGfwQ5XPwRJz/2oC\n" - b"EnPmP1SZoY9lXKUpQXHXSpDZ2rE2Klt3RHMUMHt8Zpy36E8Vwx8o\n" - b"-----END RSA PRIVATE KEY-----\n") + b"-----BEGIN RSA PRIVATE KEY-----\n" + b"MIIEowIBAAKCAQEAo8uCyhiO4JUGZV+rtNq5DBA9Lm4xkw5kTA3v6EPybs8bVXL2\n" + b"ZE6jkbo+xT4Jg/bKzUpnp1fE+T1ruGPtsPdoEmhY/P64LDNIs3sRq5U4QV9IETU1\n" + b"vIcbNNkgGhRjV8J87YNY0tV0H7tuWuZRpqnS+gjV6V9lUMkbvjMCc5IBqQc3heut\n" + b"/+fH4JwpGlGxOVXI8QAapnSy1XpCr3+PT29kydVJnIMuAoFrurojRpOQbOuVvhtA\n" + b"gARhst1Ji4nfROGYkj6eZhvkz2Bkud4/+3lGvVU5LO1vD8oY7WoGtpin3h50VcWe\n" + b"aBT4kejx4s9/G9C4R24lTH09J9HO2UUsuCqZYQIDAQABAoIBAQCfC90bCk+qaWqF\n" + b"gymC+qOWwCn4bM28gswHQb1D5r6AtKBRD8mKywVvWs7azguFVV3Fi8sspkBA2FBC\n" + b"At5p6ULoJOTL/TauzLl6djVJTCMM701WUDm2r+ZOIctXJ5bzP4n5Q4I7b0NMEL7u\n" + b"ixib4elYGr5D1vrVQAKtZHCr8gmkqyx8Mz7wkJepzBP9EeVzETCHsmiQDd5WYlO1\n" + b"C2IQYgw6MJzgM4entJ0V/GPytkodblGY95ORVK7ZhyNtda+r5BZ6/jeMW+hA3VoK\n" + b"tHSWjHt06ueVCCieZIATmYzBNt+zEz5UA2l7ksg3eWfVORJQS7a6Ef4VvbJLM9Ca\n" + b"m1kdsjelAoGBANKgvRf39i3bSuvm5VoyJuqinSb/23IH3Zo7XOZ5G164vh49E9Cq\n" + b"dOXXVxox74ppj/kbGUoOk+AvaB48zzfzNvac0a7lRHExykPH2kVrI/NwH/1OcT/x\n" + b"2e2DnFYocXcb4gbdZQ+m6X3zkxOYcONRzPVW1uMrFTWHcJveMUm4PGx7AoGBAMcU\n" + b"IRvrT6ye5se0s27gHnPweV+3xjsNtXZcK82N7duXyHmNjxrwOAv0SOhUmTkRXArM\n" + b"6aN5D8vyZBSWma2TgUKwpQYFTI+4Sp7sdkkyojGAEixJ+c5TZJNxZFrUe0FwAoic\n" + b"c2kb7ntaiEj5G+qHvykJJro5hy6uLnjiMVbAiJDTAoGAKb67241EmHAXGEwp9sdr\n" + b"2SMjnIAnQSF39UKAthkYqJxa6elXDQtLoeYdGE7/V+J2K3wIdhoPiuY6b4vD0iX9\n" + b"JcGM+WntN7YTjX2FsC588JmvbWfnoDHR7HYiPR1E58N597xXdFOzgUgORVr4PMWQ\n" + b"pqtwaZO3X2WZlvrhr+e46hMCgYBfdIdrm6jYXFjL6RkgUNZJQUTxYGzsY+ZemlNm\n" + b"fGdQo7a8kePMRuKY2MkcnXPaqTg49YgRmjq4z8CtHokRcWjJUWnPOTs8rmEZUshk\n" + b"0KJ0mbQdCFt/Uv0mtXgpFTkEZ3DPkDTGcV4oR4CRfOCl0/EU/A5VvL/U4i/mRo7h\n" + b"ye+xgQKBgD58b+9z+PR5LAJm1tZHIwb4tnyczP28PzwknxFd2qylR4ZNgvAUqGtU\n" + b"xvpUDpzMioz6zUH9YV43YNtt+5Xnzkqj+u9Mr27/H2v9XPwORGfwQ5XPwRJz/2oC\n" + b"EnPmP1SZoY9lXKUpQXHXSpDZ2rE2Klt3RHMUMHt8Zpy36E8Vwx8o\n" + b"-----END RSA PRIVATE KEY-----\n" +) _SIGNING_KEY = b"aws-crypto-public-key" _ENCRYPTION_MATERIALS = [ @@ -73,9 +72,12 @@ ), encryption_context=_ENCRYPTION_CONTEXT, signing_key=_SIGNING_KEY, - keyring_trace=[KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, - key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY})] + keyring_trace=[ + KeyringTrace( + wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}, + ) + ], ), EncryptionMaterials( algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, @@ -93,15 +95,18 @@ encryption_context=_ENCRYPTION_CONTEXT, signing_key=_SIGNING_KEY, keyring_trace=[ - KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, - key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, - KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}), + KeyringTrace( + wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + flags={ + KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, + KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY, + }, + ), # KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, # key_info=_KEY_ID), # flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY} # ) - ] + ], ), ] @@ -131,8 +136,9 @@ def test_raw_rsa_encryption_decryption(encryption_materials_samples): encryption_materials = fake_raw_rsa_keyring.on_encrypt(encryption_materials=encryption_materials_samples) # Generate decryption materials - decryption_materials = DecryptionMaterials(algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - verification_key=b"ex_verification_key") + decryption_materials = DecryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, verification_key=b"ex_verification_key" + ) # Call on_decrypt function for the keyring decryption_materials = fake_raw_rsa_keyring.on_decrypt( From 3eb4536f95816361775288fc2df032dbf2be0b94 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 16 Jul 2019 14:13:26 -0700 Subject: [PATCH 075/110] Corrected too broad exception error and deleted empty return statement from tests --- src/aws_encryption_sdk/keyring/raw_keyring.py | 2 +- test/functional/test_f_raw_aes.py | 1 - test/functional/test_f_raw_rsa.py | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 30ec3968e..b498c61f8 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -163,7 +163,7 @@ def on_decrypt_helper( encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=decryption_materials.encryption_context ) - except Exception as error: + except (ValueError, Exception) as error: logger = logging.getLogger() logger.error(error.__class__.__name__, ":", str(error)) return decryption_materials diff --git a/test/functional/test_f_raw_aes.py b/test/functional/test_f_raw_aes.py index 770063cfb..62730f782 100644 --- a/test/functional/test_f_raw_aes.py +++ b/test/functional/test_f_raw_aes.py @@ -117,4 +117,3 @@ def test_raw_aes_encryption_decryption(encryption_materials_samples): if decryption_materials.data_encryption_key: # Check if the data keys match assert encryption_materials.data_encryption_key == decryption_materials.data_encryption_key - return diff --git a/test/functional/test_f_raw_rsa.py b/test/functional/test_f_raw_rsa.py index ea3f20441..247bfa75e 100644 --- a/test/functional/test_f_raw_rsa.py +++ b/test/functional/test_f_raw_rsa.py @@ -148,4 +148,3 @@ def test_raw_rsa_encryption_decryption(encryption_materials_samples): if decryption_materials.data_encryption_key: # Check if the data keys match assert encryption_materials.data_encryption_key == decryption_materials.data_encryption_key - return From b1ad3ede0c5f533cf0704c399180befef1560e85 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 16 Jul 2019 15:51:55 -0700 Subject: [PATCH 076/110] Changed Exeception to BaseException to solve broad exception error --- src/aws_encryption_sdk/keyring/raw_keyring.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index b498c61f8..3380fbad3 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -163,7 +163,7 @@ def on_decrypt_helper( encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=decryption_materials.encryption_context ) - except (ValueError, Exception) as error: + except BaseException as error: logger = logging.getLogger() logger.error(error.__class__.__name__, ":", str(error)) return decryption_materials From 03aeae344c58d158651e1a5b9b175e15d46d3a6f Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 16 Jul 2019 17:06:18 -0700 Subject: [PATCH 077/110] Added suppress broad exception --- src/aws_encryption_sdk/keyring/raw_keyring.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 3380fbad3..1c790aa43 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -158,12 +158,13 @@ def on_decrypt_helper( ) # EncryptedData to raw key string + # noinspection PyBroadException try: plaintext_data_key = wrapping_key.decrypt( encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=decryption_materials.encryption_context ) - except BaseException as error: + except Exception as error: logger = logging.getLogger() logger.error(error.__class__.__name__, ":", str(error)) return decryption_materials From 2a248f5b0e634ef028241f7e3977af5ed3661661 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 16 Jul 2019 17:19:25 -0700 Subject: [PATCH 078/110] Added pylint disable broad exception --- src/aws_encryption_sdk/keyring/raw_keyring.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 1c790aa43..16158a727 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -158,13 +158,12 @@ def on_decrypt_helper( ) # EncryptedData to raw key string - # noinspection PyBroadException try: plaintext_data_key = wrapping_key.decrypt( encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=decryption_materials.encryption_context ) - except Exception as error: + except Exception as error: # pylint: disable=broad-except logger = logging.getLogger() logger.error(error.__class__.__name__, ":", str(error)) return decryption_materials From 92f419c53a91b5e291c4da46a31108745d6c0503 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Wed, 17 Jul 2019 18:22:04 -0700 Subject: [PATCH 079/110] Changed wrapping keys for RSA keyrings from WrappingKey to cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey/RSAPublicKey --- src/aws_encryption_sdk/keyring/raw_keyring.py | 260 ++++++++++-------- test/functional/test_f_raw_aes.py | 13 +- test/functional/test_f_raw_rsa.py | 28 +- 3 files changed, 150 insertions(+), 151 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 16158a727..93d6fd080 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -17,10 +17,12 @@ import attr import six +from cryptography.hazmat.primitives.asymmetric.padding import OAEP +from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey, RSAPublicKey from aws_encryption_sdk.exceptions import EncryptKeyError from aws_encryption_sdk.identifiers import EncryptionKeyType, KeyringTraceFlag, WrappingAlgorithm -from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey +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 @@ -55,24 +57,15 @@ def get_key_info_prefix(key_namespace, key_name, wrapping_key): def on_encrypt_helper( encryption_materials, # type: EncryptionMaterials key_provider, # type: MasterKeyInfo - wrapping_key, # type: WrappingKey - wrapping_algorithm, # type: WrappingAlgorithm - key_name, # type: bytes ): - # type: (...) -> EncryptionMaterials + # type: (...) -> bytes """Helper function for the on_encrypt function of keyring. :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials :param key_provider: Information about the key in the keyring. :type key_provider: MasterKeyInfo - :param wrapping_key: Encryption key with which to wrap plaintext data key. - :type wrapping_key: WrappingKey - :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key. - :type wrapping_algorithm: WrappingAlgorithm - :param bytes key_name: Key ID. - :return: Optionally modified encryption materials. - :rtype encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials + :return bytes: Plaintext data key """ # Check if data key already exists if not encryption_materials.data_encryption_key: @@ -98,90 +91,32 @@ def on_encrypt_helper( else: plaintext_data_key = encryption_materials.data_encryption_key.data_key - # Encrypt data key - encrypted_wrapped_key = wrapping_key.encrypt( - plaintext_data_key=plaintext_data_key, encryption_context=encryption_materials.encryption_context - ) - - # EncryptedData to EncryptedDataKey - encrypted_data_key = serialize_wrapped_key( - key_provider=key_provider, - wrapping_algorithm=wrapping_algorithm, - wrapping_key_id=key_name, - encrypted_wrapped_key=encrypted_wrapped_key, - ) - - # Update Keyring Trace - if encrypted_data_key: - keyring_trace = KeyringTrace( - wrapping_key=encrypted_data_key.key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY} - ) - - # Add encrypted data key to encryption_materials - encryption_materials.add_encrypted_data_key(encrypted_data_key=encrypted_data_key, keyring_trace=keyring_trace) - - return encryption_materials + return plaintext_data_key def on_decrypt_helper( - decryption_materials, # type: DecryptionMaterials - key_provider, # type: MasterKeyInfo - wrapping_key, # type: WrappingKey wrapping_algorithm, # type: WrappingAlgorithm key_name, # type: bytes encrypted_data_key, # type: EncryptedDataKey ): - # type: (...) -> DecryptionMaterials + # type: (...) -> EncryptedData """Helper function for the on_decrypt function of keyring. - :param decryption_materials: Decryption materials for the keyring to modify. - :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials - :param key_provider: Information about the key in the keyring. - :type key_provider: MasterKeyInfo - :param wrapping_key: Encryption key with which to wrap plaintext data key. - :type wrapping_key: WrappingKey :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key. :type wrapping_algorithm: WrappingAlgorithm :param bytes key_name: Key ID. :param encrypted_data_key: Data key encrypted with a wrapping key. :type encrypted_data_key: aws_encryption_sdk.structures.EncryptedDataKey - :return: Optionally modified decryption materials. - :rtype decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials + :return encrypted_wrapped_key: Encrypted, wrapped, data key + :rtype encrypted_wrapped_key: EncryptedData """ - # Check if plaintext data key exists - if decryption_materials.data_encryption_key: - return decryption_materials # Wrapped EncryptedDataKey to deserialized EncryptedData encrypted_wrapped_key = deserialize_wrapped_key( wrapping_algorithm=wrapping_algorithm, wrapping_key_id=key_name, wrapped_encrypted_key=encrypted_data_key ) - # EncryptedData to raw key string - try: - plaintext_data_key = wrapping_key.decrypt( - encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=decryption_materials.encryption_context - ) - - except Exception as error: # pylint: disable=broad-except - logger = logging.getLogger() - logger.error(error.__class__.__name__, ":", str(error)) - return decryption_materials - - if plaintext_data_key: - # Create a keyring trace - keyring_trace = KeyringTrace( - wrapping_key=key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} - ) - - # Update decryption materials - data_encryption_key = RawDataKey( - key_provider=MasterKeyInfo(provider_id=key_provider.provider_id, key_info=key_name), - data_key=plaintext_data_key, - ) - decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) - - return decryption_materials + return encrypted_wrapped_key @attr.s @@ -190,15 +125,14 @@ class RawAESKeyring(Keyring): :param str key_namespace: String defining the keyring. :param bytes key_name: Key ID - :param wrapping_key: Encryption key with which to wrap plaintext data key. - :type wrapping_key: WrappingKey + :param bytes wrapping_key: Encryption key with which to wrap plaintext data key. :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key. :type wrapping_algorithm: WrappingAlgorithm """ key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) - _wrapping_key = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingKey)) + _wrapping_key = attr.ib(repr=False, validator=attr.validators.instance_of(six.binary_type)) _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) def __attrs_post_init__(self): @@ -206,46 +140,68 @@ def __attrs_post_init__(self): """Prepares initial values not handled by attrs.""" self._key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name) + self._wrapping_key_structure = WrappingKey( + wrapping_algorithm=self._wrapping_algorithm, + wrapping_key=self._wrapping_key, + wrapping_key_type=EncryptionKeyType.SYMMETRIC, + ) + self._key_info_prefix = get_key_info_prefix( - key_namespace=self.key_namespace, - key_name=self.key_name, - wrapping_key=WrappingKey( - wrapping_algorithm=self._wrapping_algorithm, - wrapping_key=self._wrapping_key, - wrapping_key_type=EncryptionKeyType.SYMMETRIC, - ), + key_namespace=self.key_namespace, key_name=self.key_name, wrapping_key=self._wrapping_key_structure ) def on_encrypt(self, encryption_materials): # type: (EncryptionMaterials) -> EncryptionMaterials - """Generate a data key if not present and encrypt it using any available wrapping key. + """Generate a data key if not present and encrypt it using any available wrapping key - :param encryption_materials: Encryption materials for the keyring to modify. + :param encryption_materials: Encryption materials for the keyring to modify :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials - :returns: Optionally modified encryption materials. + :returns: Optionally modified encryption materials :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - encryption_materials = on_encrypt_helper( - encryption_materials=encryption_materials, + plaintext_data_key = on_encrypt_helper( + encryption_materials=encryption_materials, key_provider=self._key_provider + ) + + # Encrypt data key + encrypted_wrapped_key = self._wrapping_key_structure.encrypt( + plaintext_data_key=plaintext_data_key, encryption_context=encryption_materials.encryption_context + ) + + # EncryptedData to EncryptedDataKey + encrypted_data_key = serialize_wrapped_key( key_provider=self._key_provider, - wrapping_key=self._wrapping_key, wrapping_algorithm=self._wrapping_algorithm, - key_name=self.key_name, + wrapping_key_id=self.key_name, + encrypted_wrapped_key=encrypted_wrapped_key, ) + # Update Keyring Trace + if encrypted_data_key: + keyring_trace = KeyringTrace( + wrapping_key=encrypted_data_key.key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY} + ) + + # Add encrypted data key to encryption_materials + encryption_materials.add_encrypted_data_key( + encrypted_data_key=encrypted_data_key, keyring_trace=keyring_trace + ) return encryption_materials def on_decrypt(self, decryption_materials, encrypted_data_keys): # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials """Attempt to decrypt the encrypted data keys. - :param decryption_materials: Decryption materials for the keyring to modify. + :param decryption_materials: Decryption materials for the keyring to modify :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials - :param encrypted_data_keys: List of encrypted data keys. + :param encrypted_data_keys: List of encrypted data keys :type: List of `aws_encryption_sdk.structures.EncryptedDataKey` - :returns: Optionally modified decryption materials. + :returns: Optionally modified decryption materials :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials """ + if decryption_materials.data_encryption_key: + return decryption_materials + # Decrypt data key expected_key_info_len = len(self._key_info_prefix) + self._wrapping_algorithm.algorithm.iv_len for key in encrypted_data_keys: @@ -254,14 +210,34 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): and len(key.key_provider.key_info) == expected_key_info_len and key.key_provider.key_info.startswith(self._key_info_prefix) ): - decryption_materials = on_decrypt_helper( - decryption_materials=decryption_materials, - key_provider=self._key_provider, - wrapping_key=self._wrapping_key, - wrapping_algorithm=self._wrapping_algorithm, - key_name=self.key_name, - encrypted_data_key=key, + encrypted_wrapped_key = on_decrypt_helper( + wrapping_algorithm=self._wrapping_algorithm, key_name=self.key_name, encrypted_data_key=key ) + # EncryptedData to raw key string + try: + plaintext_data_key = wrapping_key.decrypt( + encrypted_wrapped_data_key=encrypted_wrapped_key, + encryption_context=decryption_materials.encryption_context, + ) + + except Exception as error: # pylint: disable=broad-except + logger = logging.getLogger() + logger.error(error.__class__.__name__, ":", str(error)) + return decryption_materials + + if plaintext_data_key: + # Create a keyring trace + keyring_trace = KeyringTrace( + wrapping_key=key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} + ) + + # Update decryption materials + data_encryption_key = RawDataKey( + key_provider=MasterKeyInfo(provider_id=key_provider.provider_id, key_info=key_name), + data_key=plaintext_data_key, + ) + decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) + if decryption_materials.data_key: return decryption_materials @@ -275,7 +251,7 @@ class RawRSAKeyring(Keyring): :param str key_namespace: String defining the keyring ID :param bytes key_name: Key ID :param wrapping_key: Encryption key with which to wrap plaintext data key - :type wrapping_key: WrappingKey + :type wrapping_key: object :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key :type wrapping_algorithm: WrappingAlgorithm :param key_provider: Complete information about the key in the keyring @@ -284,7 +260,7 @@ class RawRSAKeyring(Keyring): key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) - _wrapping_key = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingKey)) + _wrapping_key = attr.ib(repr=False, validator=attr.validators.instance_of(object)) _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) def __attrs_post_init__(self): @@ -301,13 +277,36 @@ def on_encrypt(self, encryption_materials): :returns: Optionally modified encryption materials. :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - encryption_materials = on_encrypt_helper( - encryption_materials=encryption_materials, - key_provider=self._key_provider, - wrapping_key=self._wrapping_key, - wrapping_algorithm=self._wrapping_algorithm, - key_name=self.key_name, - ) + if isinstance(self._wrapping_key, RSAPublicKey): + + plaintext_data_key = on_encrypt_helper( + encryption_materials=encryption_materials, key_provider=self._key_provider + ) + + # Encrypt data key + encrypted_wrapped_key = EncryptedData( + iv=None, ciphertext=self._wrapping_key.encrypt(plaintext=plaintext_data_key, padding=OAEP), tag=None + ) + + # EncryptedData to EncryptedDataKey + encrypted_data_key = serialize_wrapped_key( + key_provider=key_provider, + wrapping_algorithm=wrapping_algorithm, + wrapping_key_id=key_name, + encrypted_wrapped_key=encrypted_wrapped_key, + ) + + # Update Keyring Trace + if encrypted_data_key: + keyring_trace = KeyringTrace( + wrapping_key=encrypted_data_key.key_provider, + flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}, + ) + + # Add encrypted data key to encryption_materials + encryption_materials.add_encrypted_data_key( + encrypted_data_key=encrypted_data_key, keyring_trace=keyring_trace + ) return encryption_materials @@ -322,16 +321,33 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): :returns: Optionally modified decryption materials. :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials """ - # Decrypt data key - for key in encrypted_data_keys: - if key.key_provider == self._key_provider: - decryption_materials = on_decrypt_helper( - decryption_materials=decryption_materials, - key_provider=self._key_provider, - wrapping_key=self._wrapping_key, - wrapping_algorithm=self._wrapping_algorithm, - key_name=self.key_name, - encrypted_data_key=key, - ) + if isinstance(self._wrapping_key, RSAPrivateKey): + # Decrypt data key + for key in encrypted_data_keys: + if key.key_provider == self._key_provider: + encrypted_wrapped_key = on_decrypt_helper( + wrapping_algorithm=self._wrapping_algorithm, key_name=self.key_name, encrypted_data_key=key + ) + try: + plaintext_data_key = self._wrapping_key.decrypt( + ciphertext=encrypted_wrapped_key.ciphertext, padding=OAEP + ) + except Exception as error: # pylint: disable=broad-except + logger = logging.getLogger() + logger.error(error.__class__.__name__, ":", str(error)) + return decryption_materials + + if plaintext_data_key: + # Create a keyring trace + keyring_trace = KeyringTrace( + wrapping_key=key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} + ) + + # Update decryption materials + data_encryption_key = RawDataKey( + key_provider=MasterKeyInfo(provider_id=key_provider.provider_id, key_info=key_name), + data_key=plaintext_data_key, + ) + decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) return decryption_materials diff --git a/test/functional/test_f_raw_aes.py b/test/functional/test_f_raw_aes.py index 62730f782..9fa213232 100644 --- a/test/functional/test_f_raw_aes.py +++ b/test/functional/test_f_raw_aes.py @@ -70,11 +70,7 @@ KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY, }, - ), - # KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, - # key_info=_KEY_ID), - # flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY} - # ) + ) ], ), ] @@ -86,18 +82,13 @@ def test_raw_aes_encryption_decryption(encryption_materials_samples): # Initializing attributes key_namespace = _PROVIDER_ID key_name = _KEY_ID - _wrapping_key = WrappingKey( - wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, - wrapping_key=_WRAPPING_KEY, - wrapping_key_type=EncryptionKeyType.SYMMETRIC, - ) _wrapping_algorithm = WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING # Creating an instance of a raw AES keyring fake_raw_aes_keyring = RawAESKeyring( key_namespace=key_namespace, key_name=key_name, - wrapping_key=_wrapping_key, + wrapping_key=_WRAPPING_KEY, wrapping_algorithm=_wrapping_algorithm, ) diff --git a/test/functional/test_f_raw_rsa.py b/test/functional/test_f_raw_rsa.py index 247bfa75e..75f9466c8 100644 --- a/test/functional/test_f_raw_rsa.py +++ b/test/functional/test_f_raw_rsa.py @@ -14,10 +14,10 @@ import pytest from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives.asymmetric import rsa +from cryptography.hazmat.primitives import serialization -from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, KeyringTraceFlag, WrappingAlgorithm -from aws_encryption_sdk.keyring.raw_keyring import RawRSAKeyring, WrappingKey +from aws_encryption_sdk.identifiers import Algorithm, KeyringTraceFlag, WrappingAlgorithm +from aws_encryption_sdk.keyring.raw_keyring import RawRSAKeyring from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey @@ -26,9 +26,8 @@ _ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"} _PROVIDER_ID = "Random Raw Keys" _KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" -pem = rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend()) -_WRAPPING_KEY = ( - b"-----BEGIN RSA PRIVATE KEY-----\n" +_WRAPPING_KEY = serialization.load_pem_private_key( + data=b"-----BEGIN RSA PRIVATE KEY-----\n" b"MIIEowIBAAKCAQEAo8uCyhiO4JUGZV+rtNq5DBA9Lm4xkw5kTA3v6EPybs8bVXL2\n" b"ZE6jkbo+xT4Jg/bKzUpnp1fE+T1ruGPtsPdoEmhY/P64LDNIs3sRq5U4QV9IETU1\n" b"vIcbNNkgGhRjV8J87YNY0tV0H7tuWuZRpqnS+gjV6V9lUMkbvjMCc5IBqQc3heut\n" @@ -54,7 +53,9 @@ b"ye+xgQKBgD58b+9z+PR5LAJm1tZHIwb4tnyczP28PzwknxFd2qylR4ZNgvAUqGtU\n" b"xvpUDpzMioz6zUH9YV43YNtt+5Xnzkqj+u9Mr27/H2v9XPwORGfwQ5XPwRJz/2oC\n" b"EnPmP1SZoY9lXKUpQXHXSpDZ2rE2Klt3RHMUMHt8Zpy36E8Vwx8o\n" - b"-----END RSA PRIVATE KEY-----\n" + b"-----END RSA PRIVATE KEY-----\n", + password=None, + backend=default_backend(), ) _SIGNING_KEY = b"aws-crypto-public-key" @@ -101,11 +102,7 @@ KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY, }, - ), - # KeyringTrace(wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, - # key_info=_KEY_ID), - # flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY} - # ) + ) ], ), ] @@ -117,18 +114,13 @@ def test_raw_rsa_encryption_decryption(encryption_materials_samples): # Initializing attributes key_namespace = _PROVIDER_ID key_name = _KEY_ID - _wrapping_key = WrappingKey( - wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, - wrapping_key=_WRAPPING_KEY, - wrapping_key_type=EncryptionKeyType.PRIVATE, - ) _wrapping_algorithm = WrappingAlgorithm.RSA_OAEP_SHA256_MGF1 # Creating an instance of a raw AES keyring fake_raw_rsa_keyring = RawRSAKeyring( key_namespace=key_namespace, key_name=key_name, - wrapping_key=_wrapping_key, + wrapping_key=_WRAPPING_KEY, wrapping_algorithm=_wrapping_algorithm, ) From 66b56b73fb4f2de6e287d0fbf1fef7db21a86d84 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Wed, 17 Jul 2019 18:52:00 -0700 Subject: [PATCH 080/110] Fixed tox errors --- src/aws_encryption_sdk/keyring/raw_keyring.py | 17 +++++++++-------- test/functional/test_f_raw_aes.py | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 93d6fd080..74910a6b6 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -110,7 +110,6 @@ def on_decrypt_helper( :return encrypted_wrapped_key: Encrypted, wrapped, data key :rtype encrypted_wrapped_key: EncryptedData """ - # Wrapped EncryptedDataKey to deserialized EncryptedData encrypted_wrapped_key = deserialize_wrapped_key( wrapping_algorithm=wrapping_algorithm, wrapping_key_id=key_name, wrapped_encrypted_key=encrypted_data_key @@ -228,12 +227,12 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): if plaintext_data_key: # Create a keyring trace keyring_trace = KeyringTrace( - wrapping_key=key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} + wrapping_key=self._key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} ) # Update decryption materials data_encryption_key = RawDataKey( - key_provider=MasterKeyInfo(provider_id=key_provider.provider_id, key_info=key_name), + key_provider=MasterKeyInfo(provider_id=self._key_provider.provider_id, key_info=self.key_name), data_key=plaintext_data_key, ) decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) @@ -290,9 +289,9 @@ def on_encrypt(self, encryption_materials): # EncryptedData to EncryptedDataKey encrypted_data_key = serialize_wrapped_key( - key_provider=key_provider, - wrapping_algorithm=wrapping_algorithm, - wrapping_key_id=key_name, + key_provider=self._key_provider, + wrapping_algorithm=self._wrapping_algorithm, + wrapping_key_id=self._key_name, encrypted_wrapped_key=encrypted_wrapped_key, ) @@ -340,12 +339,14 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): if plaintext_data_key: # Create a keyring trace keyring_trace = KeyringTrace( - wrapping_key=key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} + wrapping_key=self._key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} ) # Update decryption materials data_encryption_key = RawDataKey( - key_provider=MasterKeyInfo(provider_id=key_provider.provider_id, key_info=key_name), + key_provider=MasterKeyInfo( + provider_id=self._key_provider.provider_id, key_info=self.key_name + ), data_key=plaintext_data_key, ) decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) diff --git a/test/functional/test_f_raw_aes.py b/test/functional/test_f_raw_aes.py index 9fa213232..df295208b 100644 --- a/test/functional/test_f_raw_aes.py +++ b/test/functional/test_f_raw_aes.py @@ -14,8 +14,8 @@ import pytest -from aws_encryption_sdk.identifiers import Algorithm, EncryptionKeyType, KeyringTraceFlag, WrappingAlgorithm -from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring, WrappingKey +from aws_encryption_sdk.identifiers import Algorithm, KeyringTraceFlag, WrappingAlgorithm +from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey From 0295db5a343c2616d70370c079506824389c057e Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Wed, 17 Jul 2019 19:03:06 -0700 Subject: [PATCH 081/110] More tox errors --- src/aws_encryption_sdk/keyring/raw_keyring.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 74910a6b6..c96932eeb 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -214,7 +214,7 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): ) # EncryptedData to raw key string try: - plaintext_data_key = wrapping_key.decrypt( + plaintext_data_key = self._wrapping_key_structure.decrypt( encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=decryption_materials.encryption_context, ) From 4adec205f4a2fd3939ef9c14bc91951e0e817ab4 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Wed, 17 Jul 2019 22:54:03 -0700 Subject: [PATCH 082/110] Moved code for generation of plaintext to be before the check for key being private or public --- src/aws_encryption_sdk/keyring/raw_keyring.py | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index c96932eeb..f3c7de88a 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -110,6 +110,7 @@ def on_decrypt_helper( :return encrypted_wrapped_key: Encrypted, wrapped, data key :rtype encrypted_wrapped_key: EncryptedData """ + # Wrapped EncryptedDataKey to deserialized EncryptedData encrypted_wrapped_key = deserialize_wrapped_key( wrapping_algorithm=wrapping_algorithm, wrapping_key_id=key_name, wrapped_encrypted_key=encrypted_data_key @@ -214,7 +215,7 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): ) # EncryptedData to raw key string try: - plaintext_data_key = self._wrapping_key_structure.decrypt( + plaintext_data_key = wrapping_key.decrypt( encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=decryption_materials.encryption_context, ) @@ -227,12 +228,12 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): if plaintext_data_key: # Create a keyring trace keyring_trace = KeyringTrace( - wrapping_key=self._key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} + wrapping_key=key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} ) # Update decryption materials data_encryption_key = RawDataKey( - key_provider=MasterKeyInfo(provider_id=self._key_provider.provider_id, key_info=self.key_name), + key_provider=MasterKeyInfo(provider_id=key_provider.provider_id, key_info=key_name), data_key=plaintext_data_key, ) decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) @@ -276,12 +277,11 @@ def on_encrypt(self, encryption_materials): :returns: Optionally modified encryption materials. :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ + plaintext_data_key = on_encrypt_helper( + encryption_materials=encryption_materials, key_provider=self._key_provider + ) if isinstance(self._wrapping_key, RSAPublicKey): - plaintext_data_key = on_encrypt_helper( - encryption_materials=encryption_materials, key_provider=self._key_provider - ) - # Encrypt data key encrypted_wrapped_key = EncryptedData( iv=None, ciphertext=self._wrapping_key.encrypt(plaintext=plaintext_data_key, padding=OAEP), tag=None @@ -289,9 +289,9 @@ def on_encrypt(self, encryption_materials): # EncryptedData to EncryptedDataKey encrypted_data_key = serialize_wrapped_key( - key_provider=self._key_provider, - wrapping_algorithm=self._wrapping_algorithm, - wrapping_key_id=self._key_name, + key_provider=key_provider, + wrapping_algorithm=wrapping_algorithm, + wrapping_key_id=key_name, encrypted_wrapped_key=encrypted_wrapped_key, ) @@ -339,14 +339,12 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): if plaintext_data_key: # Create a keyring trace keyring_trace = KeyringTrace( - wrapping_key=self._key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} + wrapping_key=key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} ) # Update decryption materials data_encryption_key = RawDataKey( - key_provider=MasterKeyInfo( - provider_id=self._key_provider.provider_id, key_info=self.key_name - ), + key_provider=MasterKeyInfo(provider_id=key_provider.provider_id, key_info=key_name), data_key=plaintext_data_key, ) decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) From 22243dc61080b1e06fff6b03673afc5555014d41 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Wed, 17 Jul 2019 23:04:42 -0700 Subject: [PATCH 083/110] Tox errors --- src/aws_encryption_sdk/keyring/raw_keyring.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index f3c7de88a..f50d96618 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -110,7 +110,6 @@ def on_decrypt_helper( :return encrypted_wrapped_key: Encrypted, wrapped, data key :rtype encrypted_wrapped_key: EncryptedData """ - # Wrapped EncryptedDataKey to deserialized EncryptedData encrypted_wrapped_key = deserialize_wrapped_key( wrapping_algorithm=wrapping_algorithm, wrapping_key_id=key_name, wrapped_encrypted_key=encrypted_data_key @@ -215,7 +214,7 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): ) # EncryptedData to raw key string try: - plaintext_data_key = wrapping_key.decrypt( + plaintext_data_key = self._wrapping_key_structure.decrypt( encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=decryption_materials.encryption_context, ) @@ -228,12 +227,12 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): if plaintext_data_key: # Create a keyring trace keyring_trace = KeyringTrace( - wrapping_key=key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} + wrapping_key=self._key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} ) # Update decryption materials data_encryption_key = RawDataKey( - key_provider=MasterKeyInfo(provider_id=key_provider.provider_id, key_info=key_name), + key_provider=MasterKeyInfo(provider_id=self._key_provider.provider_id, key_info=self.key_name), data_key=plaintext_data_key, ) decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) @@ -289,9 +288,9 @@ def on_encrypt(self, encryption_materials): # EncryptedData to EncryptedDataKey encrypted_data_key = serialize_wrapped_key( - key_provider=key_provider, - wrapping_algorithm=wrapping_algorithm, - wrapping_key_id=key_name, + key_provider=self._key_provider, + wrapping_algorithm=self._wrapping_algorithm, + wrapping_key_id=self._key_name, encrypted_wrapped_key=encrypted_wrapped_key, ) @@ -339,12 +338,14 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): if plaintext_data_key: # Create a keyring trace keyring_trace = KeyringTrace( - wrapping_key=key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} + wrapping_key=self._key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} ) # Update decryption materials data_encryption_key = RawDataKey( - key_provider=MasterKeyInfo(provider_id=key_provider.provider_id, key_info=key_name), + key_provider=MasterKeyInfo( + provider_id=self._key_provider.provider_id, key_info=self.key_name + ), data_key=plaintext_data_key, ) decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) From 07d05f7ea4b60ce6a42a96319bca58f827f9f8cd Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 18 Jul 2019 14:23:12 -0700 Subject: [PATCH 084/110] Added metaclass to base API and unit tests for base API --- src/aws_encryption_sdk/keyring/base.py | 6 ++- test/unit/test_base_keyring.py | 62 ++++++++++++++++++++++++++ test/unit/test_raw_aes_keyring.py | 0 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 test/unit/test_base_keyring.py create mode 100644 test/unit/test_raw_aes_keyring.py diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index 770b53c0b..8ccf2af09 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -11,6 +11,8 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Base class interface for Keyrings.""" +import abc + from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials from aws_encryption_sdk.structures import EncryptedDataKey @@ -21,12 +23,13 @@ pass -class Keyring(object): +class Keyring(object, metaclass=abc.ABCMeta): """Parent interface for Keyring classes. .. versionadded:: 1.5.0 """ + @abc.abstractmethod def on_encrypt(self, encryption_materials): # type: (EncryptionMaterials) -> EncryptionMaterials """Generate a data key if not present and encrypt it using any available wrapping key. @@ -39,6 +42,7 @@ def on_encrypt(self, encryption_materials): """ raise NotImplementedError("Keyring does not implement on_encrypt function") + @abc.abstractmethod def on_decrypt(self, decryption_materials, encrypted_data_keys): # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials """Attempt to decrypt the encrypted data keys. diff --git a/test/unit/test_base_keyring.py b/test/unit/test_base_keyring.py new file mode 100644 index 000000000..1c35f966b --- /dev/null +++ b/test/unit/test_base_keyring.py @@ -0,0 +1,62 @@ +# Copyright 2019 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. +"""Unit tests for base keyring.""" + +import pytest + +from aws_encryption_sdk.identifiers import Algorithm +from aws_encryption_sdk.keyring.base import Keyring +from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring +from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials + +try: # Python 3.5.0 and 3.5.1 have incompatible typing modules + from typing import Iterable # noqa pylint: disable=unused-import +except ImportError: # pragma: no cover + # We only actually need these imports when running the mypy checks + pass + +pytestmark = [pytest.mark.unit, pytest.mark.local] + +_encryption_materials = EncryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + encryption_context={"encryption": "context", "values": "here"}, + signing_key=b"aws-crypto-public-key", +) + +_decryption_materials = DecryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, verification_key=b"ex_verification_key" +) + + +def test_keyring_no_encrypt(): + class KeyringNoEncrypt(Keyring): + def on_decrypt(self, _decryption_materials, encrypted_data_keys): + # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials + decryption_materials = RawAESKeyring.on_decrypt(decryption_materials=_decryption_materials) + return decryption_materials + + with pytest.raises(TypeError) as exc_info: + KeyringNoEncrypt() + exc_info.match("Can't instantiate abstract class KeyringNoEncrypt with abstract methods on_encrypt") + + +def test_keyring_no_decrypt(): + class KeyringNoDecrypt(Keyring): + def on_encrypt(self, _encryption_materials): + # type: (EncryptionMaterials) -> EncryptionMaterials + encryption_materials = RawAESKeyring.on_encrypt(encryption_materials=_encryption_materials) + return encryption_materials + + with pytest.raises(TypeError) as exc_info: + KeyringNoDecrypt() + exc_info.match("Can't instantiate abstract class KeyringNoDecrypt with abstract methods on_decrypt") diff --git a/test/unit/test_raw_aes_keyring.py b/test/unit/test_raw_aes_keyring.py new file mode 100644 index 000000000..e69de29bb From 6df10d5c8af2a7950e7b5fa2666134f7e2435b37 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 18 Jul 2019 14:28:11 -0700 Subject: [PATCH 085/110] Changed metaclass to six.add_metaclass in base API --- src/aws_encryption_sdk/keyring/base.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index 8ccf2af09..f253ce500 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -13,6 +13,8 @@ """Base class interface for Keyrings.""" import abc +import six + from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials from aws_encryption_sdk.structures import EncryptedDataKey @@ -23,7 +25,8 @@ pass -class Keyring(object, metaclass=abc.ABCMeta): +@six.add_metaclass(abc.ABCMeta) +class Keyring(object): """Parent interface for Keyring classes. .. versionadded:: 1.5.0 From 8e47badaa68b1244ba65b2087910eca386850a9f Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 18 Jul 2019 15:18:25 -0700 Subject: [PATCH 086/110] Fixed pylint errors --- test/unit/test_base_keyring.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/test_base_keyring.py b/test/unit/test_base_keyring.py index 1c35f966b..025373c28 100644 --- a/test/unit/test_base_keyring.py +++ b/test/unit/test_base_keyring.py @@ -15,7 +15,7 @@ import pytest from aws_encryption_sdk.identifiers import Algorithm -from aws_encryption_sdk.keyring.base import Keyring +from aws_encryption_sdk.keyring.base import Keyring, EncryptedDataKey from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials From 4aae643993862aacb22c300466c650682d9ee0ce Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 18 Jul 2019 16:08:48 -0700 Subject: [PATCH 087/110] Fixed more pylint errors --- test/unit/test_base_keyring.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/test/unit/test_base_keyring.py b/test/unit/test_base_keyring.py index 025373c28..30594ddd8 100644 --- a/test/unit/test_base_keyring.py +++ b/test/unit/test_base_keyring.py @@ -13,11 +13,13 @@ """Unit tests for base keyring.""" import pytest +import six from aws_encryption_sdk.identifiers import Algorithm -from aws_encryption_sdk.keyring.base import Keyring, EncryptedDataKey +from aws_encryption_sdk.keyring.base import EncryptedDataKey, Keyring from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials +from aws_encryption_sdk.structures import MasterKeyInfo try: # Python 3.5.0 and 3.5.1 have incompatible typing modules from typing import Iterable # noqa pylint: disable=unused-import @@ -37,10 +39,28 @@ algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, verification_key=b"ex_verification_key" ) +_encrypted_data_keys = [ + EncryptedDataKey( + key_provider=MasterKeyInfo(provider_id="Random Raw Keys", key_info=b"5325b043-5843-4629-869c-64794af77ada"), + encrypted_data_key=six.b( + "\n \x8b\xc6\xfd\x91\xc7\xd5\xdc+S\x15n\xd9P\x99n\x1d\xb2\xdd\x15\xeaW" + "\xc3\x13k2\xf6\x02\xd0\x0f\x85\xec\x9e\x12\xa7\x01\x01\x01\x01\x00x" + "\x8b\xc6\xfd\x91\xc7\xd5\xdc+S\x15n\xd9P\x99n\x1d\xb2\xdd\x15\xeaW" + "\xc3\x13k2\xf6\x02\xd0\x0f\x85\xec\x9e\x00\x00\x00~0|\x06\t*\x86H" + "\x86\xf7\r\x01\x07\x06\xa0o0m\x02\x01\x000h\x06\t*\x86H\x86\xf7\r" + "\x01\x07\x010\x1e\x06\t`\x86H\x01e\x03\x04\x01.0\x11\x04\x0c\xc9rP" + "\xa1\x08t6{\xf2\xfd\xf1\xb3\x02\x01\x10\x80;D\xa4\xed`qP~c\x0f\xa0d" + "\xd5\xa2Kj\xc7\xb2\xc6\x1e\xec\xfb\x0fK\xb2*\xd5\t2\x81pR\xee\xd1" + '\x1a\xde<"\x1b\x98\x88\x8b\xf4&\xdaB\x95I\xd2\xff\x10\x13\xfc\x1aX' + "\x08,/\x8b\x8b" + ), + ) +] + def test_keyring_no_encrypt(): class KeyringNoEncrypt(Keyring): - def on_decrypt(self, _decryption_materials, encrypted_data_keys): + def on_decrypt(self, _decryption_materials, _encrypted_data_keys): # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials decryption_materials = RawAESKeyring.on_decrypt(decryption_materials=_decryption_materials) return decryption_materials From ede165addb9eb19ea12fc63b007c2fe5eee7cf00 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 18 Jul 2019 16:29:49 -0700 Subject: [PATCH 088/110] Removed RawAESKeyring instance --- test/unit/test_base_keyring.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/unit/test_base_keyring.py b/test/unit/test_base_keyring.py index 30594ddd8..02ebc0a98 100644 --- a/test/unit/test_base_keyring.py +++ b/test/unit/test_base_keyring.py @@ -17,7 +17,6 @@ from aws_encryption_sdk.identifiers import Algorithm from aws_encryption_sdk.keyring.base import EncryptedDataKey, Keyring -from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials from aws_encryption_sdk.structures import MasterKeyInfo @@ -62,8 +61,7 @@ def test_keyring_no_encrypt(): class KeyringNoEncrypt(Keyring): def on_decrypt(self, _decryption_materials, _encrypted_data_keys): # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials - decryption_materials = RawAESKeyring.on_decrypt(decryption_materials=_decryption_materials) - return decryption_materials + return _decryption_materials with pytest.raises(TypeError) as exc_info: KeyringNoEncrypt() @@ -74,8 +72,7 @@ def test_keyring_no_decrypt(): class KeyringNoDecrypt(Keyring): def on_encrypt(self, _encryption_materials): # type: (EncryptionMaterials) -> EncryptionMaterials - encryption_materials = RawAESKeyring.on_encrypt(encryption_materials=_encryption_materials) - return encryption_materials + return _encryption_materials with pytest.raises(TypeError) as exc_info: KeyringNoDecrypt() From 39dbfd31528181fd4fd5e5af44eb083ef102ab41 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 18 Jul 2019 21:24:06 -0700 Subject: [PATCH 089/110] Changed on_encrypt_helper to generate_data_key and removed on_decrypt_helper. Renamed base API unit test file --- src/aws_encryption_sdk/keyring/raw_keyring.py | 90 ++++++++----------- ...t_base_keyring.py => test_keyring_base.py} | 0 ...aes_keyring.py => test_keyring_raw_aes.py} | 0 3 files changed, 35 insertions(+), 55 deletions(-) rename test/unit/{test_base_keyring.py => test_keyring_base.py} (100%) rename test/unit/{test_raw_aes_keyring.py => test_keyring_raw_aes.py} (100%) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index f50d96618..ddd036581 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -20,7 +20,7 @@ from cryptography.hazmat.primitives.asymmetric.padding import OAEP from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey, RSAPublicKey -from aws_encryption_sdk.exceptions import EncryptKeyError +from aws_encryption_sdk.exceptions import EncryptKeyError, GenerateKeyError from aws_encryption_sdk.identifiers import EncryptionKeyType, KeyringTraceFlag, WrappingAlgorithm from aws_encryption_sdk.internal.crypto.wrapping_keys import EncryptedData, WrappingKey from aws_encryption_sdk.internal.formatting.deserialize import deserialize_wrapped_key @@ -54,7 +54,7 @@ def get_key_info_prefix(key_namespace, key_name, wrapping_key): return key_info_prefix -def on_encrypt_helper( +def generate_data_key( encryption_materials, # type: EncryptionMaterials key_provider, # type: MasterKeyInfo ): @@ -67,57 +67,25 @@ def on_encrypt_helper( :type key_provider: MasterKeyInfo :return bytes: Plaintext data key """ - # Check if data key already exists - if not encryption_materials.data_encryption_key: + # Generate data key + plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) - # Generate data key - plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) + # Check if data key is generated + if not plaintext_data_key: + raise GenerateKeyError("Unable to generate data encryption key.") - # Check if data key is generated - if not plaintext_data_key: - raise EncryptKeyError("Unable to generate data encryption key.") + # Create a keyring trace + keyring_trace = KeyringTrace(wrapping_key=key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}) - # Create a keyring trace - keyring_trace = KeyringTrace( - wrapping_key=key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY} - ) - - # plaintext_data_key to RawDataKey - data_encryption_key = RawDataKey(key_provider=key_provider, data_key=plaintext_data_key) + # plaintext_data_key to RawDataKey + data_encryption_key = RawDataKey(key_provider=key_provider, data_key=plaintext_data_key) - # Add generated data key to encryption_materials - encryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) - - else: - plaintext_data_key = encryption_materials.data_encryption_key.data_key + # Add generated data key to encryption_materials + encryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) return plaintext_data_key -def on_decrypt_helper( - wrapping_algorithm, # type: WrappingAlgorithm - key_name, # type: bytes - encrypted_data_key, # type: EncryptedDataKey -): - # type: (...) -> EncryptedData - """Helper function for the on_decrypt function of keyring. - - :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key. - :type wrapping_algorithm: WrappingAlgorithm - :param bytes key_name: Key ID. - :param encrypted_data_key: Data key encrypted with a wrapping key. - :type encrypted_data_key: aws_encryption_sdk.structures.EncryptedDataKey - :return encrypted_wrapped_key: Encrypted, wrapped, data key - :rtype encrypted_wrapped_key: EncryptedData - """ - # Wrapped EncryptedDataKey to deserialized EncryptedData - encrypted_wrapped_key = deserialize_wrapped_key( - wrapping_algorithm=wrapping_algorithm, wrapping_key_id=key_name, wrapped_encrypted_key=encrypted_data_key - ) - - return encrypted_wrapped_key - - @attr.s class RawAESKeyring(Keyring): """Public class for Raw AES Keyring. @@ -158,9 +126,12 @@ def on_encrypt(self, encryption_materials): :returns: Optionally modified encryption materials :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - plaintext_data_key = on_encrypt_helper( - encryption_materials=encryption_materials, key_provider=self._key_provider - ) + if not encryption_materials.data_encryption_key: + plaintext_data_key = generate_data_key( + encryption_materials=encryption_materials, key_provider=self._key_provider + ) + else: + plaintext_data_key = encryption_materials.data_encryption_key.data_key # Encrypt data key encrypted_wrapped_key = self._wrapping_key_structure.encrypt( @@ -209,8 +180,11 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): and len(key.key_provider.key_info) == expected_key_info_len and key.key_provider.key_info.startswith(self._key_info_prefix) ): - encrypted_wrapped_key = on_decrypt_helper( - wrapping_algorithm=self._wrapping_algorithm, key_name=self.key_name, encrypted_data_key=key + # Wrapped EncryptedDataKey to deserialized EncryptedData + encrypted_wrapped_key = deserialize_wrapped_key( + wrapping_algorithm=self._wrapping_algorithm, + wrapping_key_id=self.key_name, + wrapped_encrypted_key=key, ) # EncryptedData to raw key string try: @@ -276,9 +250,12 @@ def on_encrypt(self, encryption_materials): :returns: Optionally modified encryption materials. :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials """ - plaintext_data_key = on_encrypt_helper( - encryption_materials=encryption_materials, key_provider=self._key_provider - ) + if not encryption_materials.data_encryption_key: + plaintext_data_key = generate_data_key( + encryption_materials=encryption_materials, key_provider=self._key_provider + ) + else: + plaintext_data_key = encryption_materials.data_encryption_key.data_key if isinstance(self._wrapping_key, RSAPublicKey): # Encrypt data key @@ -323,8 +300,11 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): # Decrypt data key for key in encrypted_data_keys: if key.key_provider == self._key_provider: - encrypted_wrapped_key = on_decrypt_helper( - wrapping_algorithm=self._wrapping_algorithm, key_name=self.key_name, encrypted_data_key=key + # Wrapped EncryptedDataKey to deserialized EncryptedData + encrypted_wrapped_key = deserialize_wrapped_key( + wrapping_algorithm=self._wrapping_algorithm, + wrapping_key_id=self.key_name, + wrapped_encrypted_key=key, ) try: plaintext_data_key = self._wrapping_key.decrypt( diff --git a/test/unit/test_base_keyring.py b/test/unit/test_keyring_base.py similarity index 100% rename from test/unit/test_base_keyring.py rename to test/unit/test_keyring_base.py diff --git a/test/unit/test_raw_aes_keyring.py b/test/unit/test_keyring_raw_aes.py similarity index 100% rename from test/unit/test_raw_aes_keyring.py rename to test/unit/test_keyring_raw_aes.py From 61e8fe5fc2a7d1ee0d892b7e387e4c7a780b6c37 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 18 Jul 2019 21:27:15 -0700 Subject: [PATCH 090/110] Changed docstring for generate_data_key --- src/aws_encryption_sdk/keyring/raw_keyring.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index ddd036581..3678d1401 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -59,7 +59,7 @@ def generate_data_key( key_provider, # type: MasterKeyInfo ): # type: (...) -> bytes - """Helper function for the on_encrypt function of keyring. + """Generates plaintext data key for the keyring. :param encryption_materials: Encryption materials for the keyring to modify. :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials From e61f4a2fcf2babddd2df9368066022b3038c990c Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 18 Jul 2019 22:17:41 -0700 Subject: [PATCH 091/110] Changed decryption_materials.data_key to decryption_materials.data_encryption_key and fixed pylint errors --- src/aws_encryption_sdk/keyring/raw_keyring.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 3678d1401..8e113dfde 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -20,7 +20,7 @@ from cryptography.hazmat.primitives.asymmetric.padding import OAEP from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey, RSAPublicKey -from aws_encryption_sdk.exceptions import EncryptKeyError, GenerateKeyError +from aws_encryption_sdk.exceptions import GenerateKeyError from aws_encryption_sdk.identifiers import EncryptionKeyType, KeyringTraceFlag, WrappingAlgorithm from aws_encryption_sdk.internal.crypto.wrapping_keys import EncryptedData, WrappingKey from aws_encryption_sdk.internal.formatting.deserialize import deserialize_wrapped_key @@ -211,11 +211,15 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): ) decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) - if decryption_materials.data_key: + if decryption_materials.data_encryption_key: return decryption_materials return decryption_materials + @property + def key_provider(self): + return self._key_provider + @attr.s class RawRSAKeyring(Keyring): @@ -329,5 +333,7 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): data_key=plaintext_data_key, ) decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) + if decryption_materials.data_encryption_key: + return decryption_materials return decryption_materials From 89f8a2c09dfdfac36c5a1e472fc23b318fb72f4a Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Thu, 18 Jul 2019 22:30:45 -0700 Subject: [PATCH 092/110] Fixed pylint errors --- src/aws_encryption_sdk/keyring/raw_keyring.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 8e113dfde..ba0566c0a 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -216,10 +216,6 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): return decryption_materials - @property - def key_provider(self): - return self._key_provider - @attr.s class RawRSAKeyring(Keyring): From fbf351f4e2fd1ab3ae6c3f136e14c50707fced1f Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Sat, 20 Jul 2019 01:24:12 -0700 Subject: [PATCH 093/110] Changed raw keyrings to have class methods for PEM and DER encoded keys --- src/aws_encryption_sdk/keyring/raw_keyring.py | 103 ++++++++--- test/functional/test_f_raw_rsa.py | 60 ++---- test/unit/test_keyring_raw_aes.py | 174 ++++++++++++++++++ 3 files changed, 267 insertions(+), 70 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index ba0566c0a..05f3f76ed 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -17,8 +17,9 @@ import attr import six -from cryptography.hazmat.primitives.asymmetric.padding import OAEP -from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey, RSAPublicKey +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric import padding, rsa from aws_encryption_sdk.exceptions import GenerateKeyError from aws_encryption_sdk.identifiers import EncryptionKeyType, KeyringTraceFlag, WrappingAlgorithm @@ -31,7 +32,7 @@ from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey try: # Python 3.5.0 and 3.5.1 have incompatible typing modules - from typing import Iterable # noqa pylint: disable=unused-import + from typing import Iterable, Union # noqa pylint: disable=unused-import except ImportError: # pragma: no cover # We only actually need these imports when running the mypy checks pass @@ -233,9 +234,51 @@ class RawRSAKeyring(Keyring): key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) + # _wrapping_key = attr.ib(repr=False, validator=attr.validators.in_([rsa.RSAPrivateKey, rsa.RSAPublicKey])) + # ----- need to figure out how to do this correctly _wrapping_key = attr.ib(repr=False, validator=attr.validators.instance_of(object)) _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) + @classmethod + def fromPEMEncoding(cls): + key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) + key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) + _encoded_key = attr.ib(validator=attr.validators.instance_of(six.binary_type)) + _password = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(six.binary_type))) + _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) + if _password: + loaded_wrapping_key = serialization.load_pem_private_key( + data=_encoded_key, password=_password, backend=default_backend() + ) + else: + loaded_wrapping_key = serialization.load_pem_public_key(data=_encoded_key, backend=default_backend()) + return RawRSAKeyring( + key_namespace=key_namespace, + key_name=key_name, + wrapping_key=loaded_wrapping_key, + wrapping_algorithm=_wrapping_algorithm, + ) + + @classmethod + def fromDEREncoding(cls): + key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) + key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) + _encoded_key = attr.ib(validator=attr.validators.instance_of(six.binary_type)) + _password = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(six.binary_type))) + _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) + if _password: + loaded_wrapping_key = serialization.load_der_private_key( + data=_encoded_key, password=_password, backend=default_backend() + ) + else: + loaded_wrapping_key = serialization.load_der_public_key(data=_encoded_key, backend=default_backend()) + return RawRSAKeyring( + key_namespace=key_namespace, + key_name=key_name, + wrapping_key=loaded_wrapping_key, + wrapping_algorithm=_wrapping_algorithm, + ) + def __attrs_post_init__(self): # type: () -> None """Prepares initial values not handled by attrs.""" @@ -256,32 +299,44 @@ def on_encrypt(self, encryption_materials): ) else: plaintext_data_key = encryption_materials.data_encryption_key.data_key - if isinstance(self._wrapping_key, RSAPublicKey): + if isinstance(self._wrapping_key, rsa.RSAPublicKey): # Encrypt data key encrypted_wrapped_key = EncryptedData( - iv=None, ciphertext=self._wrapping_key.encrypt(plaintext=plaintext_data_key, padding=OAEP), tag=None + iv=None, + ciphertext=self._wrapping_key.encrypt( + plaintext=plaintext_data_key, padding=self._wrapping_algorithm.padding + ), + tag=None, ) - - # EncryptedData to EncryptedDataKey - encrypted_data_key = serialize_wrapped_key( - key_provider=self._key_provider, - wrapping_algorithm=self._wrapping_algorithm, - wrapping_key_id=self._key_name, - encrypted_wrapped_key=encrypted_wrapped_key, + else: + # Encrypt data key + encrypted_wrapped_key = EncryptedData( + iv=None, + ciphertext=self._wrapping_key.public_key().encrypt( + plaintext=plaintext_data_key, padding=self._wrapping_algorithm.padding + ), + tag=None, ) - # Update Keyring Trace - if encrypted_data_key: - keyring_trace = KeyringTrace( - wrapping_key=encrypted_data_key.key_provider, - flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}, - ) + # EncryptedData to EncryptedDataKey + encrypted_data_key = serialize_wrapped_key( + key_provider=self._key_provider, + wrapping_algorithm=self._wrapping_algorithm, + wrapping_key_id=self.key_name, + encrypted_wrapped_key=encrypted_wrapped_key, + ) - # Add encrypted data key to encryption_materials - encryption_materials.add_encrypted_data_key( - encrypted_data_key=encrypted_data_key, keyring_trace=keyring_trace - ) + # Update Keyring Trace + if encrypted_data_key: + keyring_trace = KeyringTrace( + wrapping_key=encrypted_data_key.key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY} + ) + + # Add encrypted data key to encryption_materials + encryption_materials.add_encrypted_data_key( + encrypted_data_key=encrypted_data_key, keyring_trace=keyring_trace + ) return encryption_materials @@ -296,7 +351,7 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): :returns: Optionally modified decryption materials. :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials """ - if isinstance(self._wrapping_key, RSAPrivateKey): + if isinstance(self._wrapping_key, rsa.RSAPrivateKey): # Decrypt data key for key in encrypted_data_keys: if key.key_provider == self._key_provider: @@ -308,7 +363,7 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): ) try: plaintext_data_key = self._wrapping_key.decrypt( - ciphertext=encrypted_wrapped_key.ciphertext, padding=OAEP + ciphertext=encrypted_wrapped_key.ciphertext, padding=self._wrapping_algorithm.padding ) except Exception as error: # pylint: disable=broad-except logger = logging.getLogger() diff --git a/test/functional/test_f_raw_rsa.py b/test/functional/test_f_raw_rsa.py index 75f9466c8..3ebb5510f 100644 --- a/test/functional/test_f_raw_rsa.py +++ b/test/functional/test_f_raw_rsa.py @@ -14,7 +14,7 @@ import pytest from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric import rsa from aws_encryption_sdk.identifiers import Algorithm, KeyringTraceFlag, WrappingAlgorithm from aws_encryption_sdk.keyring.raw_keyring import RawRSAKeyring @@ -26,38 +26,8 @@ _ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"} _PROVIDER_ID = "Random Raw Keys" _KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" -_WRAPPING_KEY = serialization.load_pem_private_key( - data=b"-----BEGIN RSA PRIVATE KEY-----\n" - b"MIIEowIBAAKCAQEAo8uCyhiO4JUGZV+rtNq5DBA9Lm4xkw5kTA3v6EPybs8bVXL2\n" - b"ZE6jkbo+xT4Jg/bKzUpnp1fE+T1ruGPtsPdoEmhY/P64LDNIs3sRq5U4QV9IETU1\n" - b"vIcbNNkgGhRjV8J87YNY0tV0H7tuWuZRpqnS+gjV6V9lUMkbvjMCc5IBqQc3heut\n" - b"/+fH4JwpGlGxOVXI8QAapnSy1XpCr3+PT29kydVJnIMuAoFrurojRpOQbOuVvhtA\n" - b"gARhst1Ji4nfROGYkj6eZhvkz2Bkud4/+3lGvVU5LO1vD8oY7WoGtpin3h50VcWe\n" - b"aBT4kejx4s9/G9C4R24lTH09J9HO2UUsuCqZYQIDAQABAoIBAQCfC90bCk+qaWqF\n" - b"gymC+qOWwCn4bM28gswHQb1D5r6AtKBRD8mKywVvWs7azguFVV3Fi8sspkBA2FBC\n" - b"At5p6ULoJOTL/TauzLl6djVJTCMM701WUDm2r+ZOIctXJ5bzP4n5Q4I7b0NMEL7u\n" - b"ixib4elYGr5D1vrVQAKtZHCr8gmkqyx8Mz7wkJepzBP9EeVzETCHsmiQDd5WYlO1\n" - b"C2IQYgw6MJzgM4entJ0V/GPytkodblGY95ORVK7ZhyNtda+r5BZ6/jeMW+hA3VoK\n" - b"tHSWjHt06ueVCCieZIATmYzBNt+zEz5UA2l7ksg3eWfVORJQS7a6Ef4VvbJLM9Ca\n" - b"m1kdsjelAoGBANKgvRf39i3bSuvm5VoyJuqinSb/23IH3Zo7XOZ5G164vh49E9Cq\n" - b"dOXXVxox74ppj/kbGUoOk+AvaB48zzfzNvac0a7lRHExykPH2kVrI/NwH/1OcT/x\n" - b"2e2DnFYocXcb4gbdZQ+m6X3zkxOYcONRzPVW1uMrFTWHcJveMUm4PGx7AoGBAMcU\n" - b"IRvrT6ye5se0s27gHnPweV+3xjsNtXZcK82N7duXyHmNjxrwOAv0SOhUmTkRXArM\n" - b"6aN5D8vyZBSWma2TgUKwpQYFTI+4Sp7sdkkyojGAEixJ+c5TZJNxZFrUe0FwAoic\n" - b"c2kb7ntaiEj5G+qHvykJJro5hy6uLnjiMVbAiJDTAoGAKb67241EmHAXGEwp9sdr\n" - b"2SMjnIAnQSF39UKAthkYqJxa6elXDQtLoeYdGE7/V+J2K3wIdhoPiuY6b4vD0iX9\n" - b"JcGM+WntN7YTjX2FsC588JmvbWfnoDHR7HYiPR1E58N597xXdFOzgUgORVr4PMWQ\n" - b"pqtwaZO3X2WZlvrhr+e46hMCgYBfdIdrm6jYXFjL6RkgUNZJQUTxYGzsY+ZemlNm\n" - b"fGdQo7a8kePMRuKY2MkcnXPaqTg49YgRmjq4z8CtHokRcWjJUWnPOTs8rmEZUshk\n" - b"0KJ0mbQdCFt/Uv0mtXgpFTkEZ3DPkDTGcV4oR4CRfOCl0/EU/A5VvL/U4i/mRo7h\n" - b"ye+xgQKBgD58b+9z+PR5LAJm1tZHIwb4tnyczP28PzwknxFd2qylR4ZNgvAUqGtU\n" - b"xvpUDpzMioz6zUH9YV43YNtt+5Xnzkqj+u9Mr27/H2v9XPwORGfwQ5XPwRJz/2oC\n" - b"EnPmP1SZoY9lXKUpQXHXSpDZ2rE2Klt3RHMUMHt8Zpy36E8Vwx8o\n" - b"-----END RSA PRIVATE KEY-----\n", - password=None, - backend=default_backend(), -) _SIGNING_KEY = b"aws-crypto-public-key" +_WRAPPING_ALGORITHM = WrappingAlgorithm.RSA_OAEP_SHA256_MGF1 _ENCRYPTION_MATERIALS = [ EncryptionMaterials( @@ -107,22 +77,20 @@ ), ] - -@pytest.mark.parametrize("encryption_materials_samples", _ENCRYPTION_MATERIALS) -def test_raw_rsa_encryption_decryption(encryption_materials_samples): - - # Initializing attributes - key_namespace = _PROVIDER_ID - key_name = _KEY_ID - _wrapping_algorithm = WrappingAlgorithm.RSA_OAEP_SHA256_MGF1 - - # Creating an instance of a raw AES keyring - fake_raw_rsa_keyring = RawRSAKeyring( +_RAW_RSA_KEYRINGS = [ + RawRSAKeyring( key_namespace=key_namespace, key_name=key_name, - wrapping_key=_WRAPPING_KEY, - wrapping_algorithm=_wrapping_algorithm, - ) + wrapping_key=rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend()), + wrapping_algorithm=_WRAPPING_ALGORITHM, + ), + RawRSAKeyring.fromPEMEncoding() +] + + +@pytest.mark.parametrize("encryption_materials_samples", _ENCRYPTION_MATERIALS) +@pytest.mark.parametrize("fake_raw_rsa_keyring", _RAW_RSA_KEYRINGS) +def test_raw_rsa_encryption_decryption(encryption_materials_samples, fake_raw_rsa_keyring): # Call on_encrypt function for the keyring encryption_materials = fake_raw_rsa_keyring.on_encrypt(encryption_materials=encryption_materials_samples) diff --git a/test/unit/test_keyring_raw_aes.py b/test/unit/test_keyring_raw_aes.py index e69de29bb..b202f805c 100644 --- a/test/unit/test_keyring_raw_aes.py +++ b/test/unit/test_keyring_raw_aes.py @@ -0,0 +1,174 @@ +# Copyright 2019 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. +"""Unit tests for Raw AES keyring.""" + +import pytest +import six +from mock import MagicMock, patch, sentinel + +from aws_encryption_sdk.exceptions import GenerateKeyError +from aws_encryption_sdk.identifiers import Algorithm, KeyringTraceFlag, WrappingAlgorithm +from aws_encryption_sdk.keyring.base import EncryptedDataKey, Keyring +from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring +from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials +from aws_encryption_sdk.structures import KeyringTrace, MasterKeyInfo, RawDataKey + +from .test_values import VALUES + +try: # Python 3.5.0 and 3.5.1 have incompatible typing modules + from typing import Iterable # noqa pylint: disable=unused-import +except ImportError: # pragma: no cover + # We only actually need these imports when running the mypy checks + pass + +pytestmark = [pytest.mark.unit, pytest.mark.local] + +_ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"} +_PROVIDER_ID = "Random Raw Keys" +_KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" +_WRAPPING_KEY = b"\xeby-\x80A6\x15rA8\x83#,\xe4\xab\xac`\xaf\x99Z\xc1\xce\xdb\xb6\x0f\xb7\x805\xb2\x14J3" +_SIGNING_KEY = b"aws-crypto-public-key" +_DATA_KEY = ( + b"\x00\xfa\x8c\xdd\x08Au\xc6\x92_4\xc5\xfb\x90\xaf\x8f\xa1D\xaf\xcc\xd25" b"\xa8\x0b\x0b\x16\x92\x91W\x01\xb7\x84" +) +_ENCRYPTION_MATERIALS_WITH_DATA_KEY = EncryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + data_encryption_key=RawDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + ), + encryption_context=_ENCRYPTION_CONTEXT, + signing_key=_SIGNING_KEY, + keyring_trace=[ + KeyringTrace( + wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}, + ) + ], +) + +_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY = EncryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + encryption_context=_ENCRYPTION_CONTEXT, + signing_key=_SIGNING_KEY, +) + +_ENCRYPTION_MATERIALS_WITH_ENCRYPTED_DATA_KEY = EncryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + data_encryption_key=RawDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + ), + encrypted_data_keys=[ + EncryptedDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" + b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", + ) + ], + encryption_context=_ENCRYPTION_CONTEXT, + signing_key=_SIGNING_KEY, + keyring_trace=[ + KeyringTrace( + wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}, + ) + ], +) + + +class TestRawAESKeyring(object): + @pytest.fixture(autouse=True) + def apply_fixtures(self): + self.mock_encrypted_data_key = EncryptedDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + encrypted_data_key=VALUES["encrypted_data_key"], + ) + self.mock_encryption_materials = MagicMock() + self.mock_encryption_materials.__class__ = EncryptionMaterials + + def test_parent(self): + assert issubclass(RawAESKeyring, Keyring) + + # def test_initialization(self): + # test = RawAESKeyring( + # key_namespace=_PROVIDER_ID, + # key_name=_KEY_ID, + # wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, + # wrapping_key=_WRAPPING_KEY, + # ) + # assert test.key_provider() == self.mock_encrypted_data_key.key_provider + + @patch("aws_encryption_sdk.keyring.raw_keyring.generate_data_key") + def test_data_encryption_key_provided(self, mock_generate_data_key): + mock_generate_data_key.return_value = _DATA_KEY + test_raw_aes_keyring = RawAESKeyring( + key_namespace=_PROVIDER_ID, + key_name=_KEY_ID, + wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, + wrapping_key=_WRAPPING_KEY, + ) + + test = test_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITH_DATA_KEY) + # Check if keyring is generated + assert not mock_generate_data_key.called + + # Check if data encryption key is encrypted + assert test.encrypted_data_keys is not None + + def test_data_encryption_key_generated(self): + test_raw_aes_keyring = RawAESKeyring( + key_namespace=_PROVIDER_ID, + key_name=_KEY_ID, + wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, + wrapping_key=_WRAPPING_KEY, + ) + test = test_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY) + + # Check if key is generated + if not test.data_encryption_key: + # Check if error thrown if data key is not generated + assert pytest.raises(GenerateKeyError, "Unable to generate data encryption key.") + else: + # Check if data key is generated + assert test.data_encryption_key and test.data_encryption_key is not None + assert test.encrypted_data_keys and test.encrypted_data_keys is not None + + @patch("aws_encryption_sdk.keyring.raw_keyring.generate_data_key") + def test_encrypted_data_key_provided(self, mock_generate_data_key): + mock_generate_data_key.return_value = _DATA_KEY + test_raw_aes_keyring = RawAESKeyring( + key_namespace=_PROVIDER_ID, + key_name=_KEY_ID, + wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, + wrapping_key=_WRAPPING_KEY, + ) + test = test_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITH_ENCRYPTED_DATA_KEY) + + # Check if generate_data_key is called + assert not mock_generate_data_key.called + # + # Check if encrypt is called + assert len(test.encrypted_data_keys) == len(_ENCRYPTION_MATERIALS_WITH_ENCRYPTED_DATA_KEY.encrypted_data_keys) + + # @patch("aws_encryption_sdk.key_providers.raw.os.urandom") + # def test_data_key_not_generated(self, mock_os_urandom): + # mock_os_urandom.return_value = None + # test_raw_aes_keyring = RawAESKeyring( + # key_namespace=_PROVIDER_ID, + # key_name=_KEY_ID, + # wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, + # wrapping_key=_WRAPPING_KEY, + # ) + # test = test_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY) + # assert pytest.raises(GenerateKeyError, "Unable to generate data encryption key.") From fb8b7b8f1ee1407c81cfdde0d4d172a26d3e33db Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Mon, 22 Jul 2019 13:17:55 -0700 Subject: [PATCH 094/110] Unit tests for raw keyrings --- examples/src/sample_aes.py | 78 ++++++ src/aws_encryption_sdk/keyring/raw_keyring.py | 52 ++-- ...f_raw_aes.py => test_f_keyring_raw_aes.py} | 11 +- ...f_raw_rsa.py => test_f_keyring_raw_rsa.py} | 62 ++++- test/unit/test_keyring_raw_aes.py | 73 +++++- test/unit/test_keyring_raw_rsa.py | 244 ++++++++++++++++++ test/unit/test_utils.py | 27 ++ 7 files changed, 514 insertions(+), 33 deletions(-) create mode 100644 examples/src/sample_aes.py rename test/functional/{test_f_raw_aes.py => test_f_keyring_raw_aes.py} (93%) rename test/functional/{test_f_raw_rsa.py => test_f_keyring_raw_rsa.py} (53%) create mode 100644 test/unit/test_keyring_raw_rsa.py diff --git a/examples/src/sample_aes.py b/examples/src/sample_aes.py new file mode 100644 index 000000000..d9d37f37a --- /dev/null +++ b/examples/src/sample_aes.py @@ -0,0 +1,78 @@ +# Copyright 2019 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. +"""Functional tests for Raw AES keyring encryption decryption path.""" + +import pytest + +from aws_encryption_sdk.identifiers import Algorithm, WrappingAlgorithm +from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring +from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials + +pytestmark = [pytest.mark.functional, pytest.mark.local] + +_ENCRYPTION_CONTEXT = {"key_a": "value_a", "key_b": "value_b", "key_c": "value_c"} +_PROVIDER_ID = "Random Raw Keys" +_KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" +_WRAPPING_KEY = b"12345678901234567890123456789012" +_SIGNING_KEY = b"aws-crypto-public-key" + +_ENCRYPTION_MATERIALS = EncryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + encryption_context=_ENCRYPTION_CONTEXT, + signing_key=_SIGNING_KEY, + ) + + +def sample_aes_encryption_decryption(): + + # Initializing attributes + key_namespace = _PROVIDER_ID + key_name = _KEY_ID + _wrapping_algorithm = WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING + + # Creating an instance of a raw AES keyring + fake_raw_aes_keyring = RawAESKeyring( + key_namespace=key_namespace, + key_name=key_name, + wrapping_key=_WRAPPING_KEY, + wrapping_algorithm=_wrapping_algorithm, + ) + + # Call on_encrypt function for the keyring + encryption_materials = fake_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS) + + print("PLAINTEXT DATA KEY") + print(encryption_materials.data_encryption_key.data_key) + + print("ENCRYPTED DATA KEY") + print(encryption_materials.encrypted_data_keys) + + # Generate decryption materials + decryption_materials = DecryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, verification_key=b"ex_verification_key" + ) + + # Call on_decrypt function for the keyring + decryption_materials = fake_raw_aes_keyring.on_decrypt( + decryption_materials=decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys + ) + + print("DECRYPTED DATA KEY") + print(decryption_materials.data_encryption_key.data_key) + + if decryption_materials.data_encryption_key: + # Check if the data keys match + assert encryption_materials.data_encryption_key == decryption_materials.data_encryption_key + + +sample_aes_encryption_decryption() diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py index 05f3f76ed..3cfdf9c21 100644 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ b/src/aws_encryption_sdk/keyring/raw_keyring.py @@ -72,7 +72,7 @@ def generate_data_key( plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) # Check if data key is generated - if not plaintext_data_key: + if not plaintext_data_key or plaintext_data_key is None: raise GenerateKeyError("Unable to generate data encryption key.") # Create a keyring trace @@ -134,6 +134,10 @@ def on_encrypt(self, encryption_materials): else: plaintext_data_key = encryption_materials.data_encryption_key.data_key + # Check if data key exists + if not plaintext_data_key or plaintext_data_key is None: + raise GenerateKeyError("Unable to generate data encryption key.") + # Encrypt data key encrypted_wrapped_key = self._wrapping_key_structure.encrypt( plaintext_data_key=plaintext_data_key, encryption_context=encryption_materials.encryption_context @@ -195,7 +199,7 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): ) except Exception as error: # pylint: disable=broad-except - logger = logging.getLogger() + logger = logging.getLogger(__name__) logger.error(error.__class__.__name__, ":", str(error)) return decryption_materials @@ -240,43 +244,43 @@ class RawRSAKeyring(Keyring): _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) @classmethod - def fromPEMEncoding(cls): - key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) - key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) - _encoded_key = attr.ib(validator=attr.validators.instance_of(six.binary_type)) - _password = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(six.binary_type))) - _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) - if _password: + def fromPEMEncoding(cls, key_namespace, key_name, encoded_key, password, wrapping_algorithm): + # key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) + # key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) + # _encoded_key = attr.ib(validator=attr.validators.instance_of(six.binary_type)) + # _password = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(six.binary_type))) + # _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) + if password: loaded_wrapping_key = serialization.load_pem_private_key( - data=_encoded_key, password=_password, backend=default_backend() + data=encoded_key, password=password, backend=default_backend() ) else: - loaded_wrapping_key = serialization.load_pem_public_key(data=_encoded_key, backend=default_backend()) - return RawRSAKeyring( + loaded_wrapping_key = serialization.load_pem_public_key(data=encoded_key, backend=default_backend()) + return cls( key_namespace=key_namespace, key_name=key_name, wrapping_key=loaded_wrapping_key, - wrapping_algorithm=_wrapping_algorithm, + wrapping_algorithm=wrapping_algorithm, ) @classmethod - def fromDEREncoding(cls): - key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) - key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) - _encoded_key = attr.ib(validator=attr.validators.instance_of(six.binary_type)) - _password = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(six.binary_type))) - _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) - if _password: + def fromDEREncoding(cls, key_namespace, key_name, encoded_key, password, wrapping_algorithm): + # key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) + # key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) + # _encoded_key = attr.ib(validator=attr.validators.instance_of(six.binary_type)) + # _password = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(six.binary_type))) + # _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) + if password: loaded_wrapping_key = serialization.load_der_private_key( - data=_encoded_key, password=_password, backend=default_backend() + data=encoded_key, password=password, backend=default_backend() ) else: - loaded_wrapping_key = serialization.load_der_public_key(data=_encoded_key, backend=default_backend()) - return RawRSAKeyring( + loaded_wrapping_key = serialization.load_der_public_key(data=encoded_key, backend=default_backend()) + return cls( key_namespace=key_namespace, key_name=key_name, wrapping_key=loaded_wrapping_key, - wrapping_algorithm=_wrapping_algorithm, + wrapping_algorithm=wrapping_algorithm, ) def __attrs_post_init__(self): diff --git a/test/functional/test_f_raw_aes.py b/test/functional/test_f_keyring_raw_aes.py similarity index 93% rename from test/functional/test_f_raw_aes.py rename to test/functional/test_f_keyring_raw_aes.py index df295208b..18c0638bc 100644 --- a/test/functional/test_f_raw_aes.py +++ b/test/functional/test_f_keyring_raw_aes.py @@ -24,7 +24,7 @@ _ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"} _PROVIDER_ID = "Random Raw Keys" _KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" -_WRAPPING_KEY = b"\xeby-\x80A6\x15rA8\x83#,\xe4\xab\xac`\xaf\x99Z\xc1\xce\xdb\xb6\x0f\xb7\x805\xb2\x14J3" +_WRAPPING_KEY = b"12345678901234567890123456789012" _SIGNING_KEY = b"aws-crypto-public-key" _ENCRYPTION_MATERIALS = [ @@ -95,6 +95,9 @@ def test_raw_aes_encryption_decryption(encryption_materials_samples): # Call on_encrypt function for the keyring encryption_materials = fake_raw_aes_keyring.on_encrypt(encryption_materials=encryption_materials_samples) + print("PLAINTEXT DATA KEY") + print(encryption_materials.data_encryption_key) + # Generate decryption materials decryption_materials = DecryptionMaterials( algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, verification_key=b"ex_verification_key" @@ -105,6 +108,6 @@ def test_raw_aes_encryption_decryption(encryption_materials_samples): decryption_materials=decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys ) - if decryption_materials.data_encryption_key: - # Check if the data keys match - assert encryption_materials.data_encryption_key == decryption_materials.data_encryption_key + # if decryption_materials.data_encryption_key: + # # Check if the data keys match + assert encryption_materials.data_encryption_key == decryption_materials.data_encryption_key diff --git a/test/functional/test_f_raw_rsa.py b/test/functional/test_f_keyring_raw_rsa.py similarity index 53% rename from test/functional/test_f_raw_rsa.py rename to test/functional/test_f_keyring_raw_rsa.py index 3ebb5510f..7b39e01e0 100644 --- a/test/functional/test_f_raw_rsa.py +++ b/test/functional/test_f_keyring_raw_rsa.py @@ -79,12 +79,68 @@ _RAW_RSA_KEYRINGS = [ RawRSAKeyring( - key_namespace=key_namespace, - key_name=key_name, + key_namespace=_PROVIDER_ID, + key_name=_KEY_ID, wrapping_key=rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend()), wrapping_algorithm=_WRAPPING_ALGORITHM, ), - RawRSAKeyring.fromPEMEncoding() + # RawRSAKeyring.fromPEMEncoding( + # key_namespace=_PROVIDER_ID, + # key_name=_KEY_ID, + # encoded_key=( + # b"-----BEGIN RSA PRIVATE KEY-----" + # b"MIICXgIBAAKBgQCUjhI8YRPXV8Gfofbg/" + # b"PLjWw2AzowQTPErLU2z3+xGqElMdzdiC4Ta43DFWZg34Eg0X8kQPAeoe8h3cRSMo" + # b"77eSOHt2dPo7OfTfZqsH8766fivHIKVxBYPX8SZYIUhMtRnlg3uqch9BksfRop+h" + # b"f8h/H3lfervJoevS2CXYB9/iwIDAQABAoGBAIqeGzQOHbaGI51yQ2zjez1dPDdiB" + # b"F49fZideHEM1GuGIodgguRQ/VJGgncUSC5zcMy2SGaGrVqwznltohAtxy4rZp0eh" + # b"2O3aHYi9Wehd0SPLh+qwu7mJDuh0z15hmCOue070FnUtyuSwhXLwDrbot2+5HbmF" + # b"9clJLI5tv92gvIpAkEA+Bv5i8XJNPN1rao31aQFoi9bFIOEclk3b1RbLX6mpZBFS" + # b"U9CNUy0RQNC0+H3KZ5CTvsyFGpMfTdiFc/Qdesk3QJBAJlHjrvoadP+PU3zXYrWR" + # b"D5EryyTxaP1bOjrp9xLuQBeU8x7EVJdpoul9OmwcT3NrAqvxDE9okjha2tjCI6O2" + # b"4cCQQDMyOJPYL/zaaPO5LlTKB/SPv4RT4BplYPw6xKa2XeZHhxiJv5B2f7NG6T0G" + # b"AWWn16hrCoouZhKngTidfXc7motAkA/KiTgvKr3yHp86AAxWZDv1CAYD6FPqrDB3" + # b"3LiLnZDd5uy1ThTJ/Kc87vUnXhdDqeKE9qWrB53SCWbMElzbd17AkEA4DMp+6ngM" + # b"o6sS0dY1X6nTLqgvK3B0z5GCAdSEy3Y8jh995Lrl+hy88HzuwUkQwwPlZkFhUNCx" + # b"edrC6cTKE5xLA==" + # b"-----END RSA PRIVATE KEY-----" + # ), + # password=None, + # wrapping_algorithm=_WRAPPING_ALGORITHM, + # ), + # RawRSAKeyring.fromDEREncoding( + # key_namespace=_PROVIDER_ID, + # key_name=_KEY_ID, + # encoded_key=b"-----BEGIN RSA PRIVATE KEY-----\n" + # b"MIIEowIBAAKCAQEAo8uCyhiO4JUGZV+rtNq5DBA9Lm4xkw5kTA3v6EPybs8bVXL2\n" + # b"ZE6jkbo+xT4Jg/bKzUpnp1fE+T1ruGPtsPdoEmhY/P64LDNIs3sRq5U4QV9IETU1\n" + # b"vIcbNNkgGhRjV8J87YNY0tV0H7tuWuZRpqnS+gjV6V9lUMkbvjMCc5IBqQc3heut\n" + # b"/+fH4JwpGlGxOVXI8QAapnSy1XpCr3+PT29kydVJnIMuAoFrurojRpOQbOuVvhtA\n" + # b"gARhst1Ji4nfROGYkj6eZhvkz2Bkud4/+3lGvVU5LO1vD8oY7WoGtpin3h50VcWe\n" + # b"aBT4kejx4s9/G9C4R24lTH09J9HO2UUsuCqZYQIDAQABAoIBAQCfC90bCk+qaWqF\n" + # b"gymC+qOWwCn4bM28gswHQb1D5r6AtKBRD8mKywVvWs7azguFVV3Fi8sspkBA2FBC\n" + # b"At5p6ULoJOTL/TauzLl6djVJTCMM701WUDm2r+ZOIctXJ5bzP4n5Q4I7b0NMEL7u\n" + # b"ixib4elYGr5D1vrVQAKtZHCr8gmkqyx8Mz7wkJepzBP9EeVzETCHsmiQDd5WYlO1\n" + # b"C2IQYgw6MJzgM4entJ0V/GPytkodblGY95ORVK7ZhyNtda+r5BZ6/jeMW+hA3VoK\n" + # b"tHSWjHt06ueVCCieZIATmYzBNt+zEz5UA2l7ksg3eWfVORJQS7a6Ef4VvbJLM9Ca\n" + # b"m1kdsjelAoGBANKgvRf39i3bSuvm5VoyJuqinSb/23IH3Zo7XOZ5G164vh49E9Cq\n" + # b"dOXXVxox74ppj/kbGUoOk+AvaB48zzfzNvac0a7lRHExykPH2kVrI/NwH/1OcT/x\n" + # b"2e2DnFYocXcb4gbdZQ+m6X3zkxOYcONRzPVW1uMrFTWHcJveMUm4PGx7AoGBAMcU\n" + # b"IRvrT6ye5se0s27gHnPweV+3xjsNtXZcK82N7duXyHmNjxrwOAv0SOhUmTkRXArM\n" + # b"6aN5D8vyZBSWma2TgUKwpQYFTI+4Sp7sdkkyojGAEixJ+c5TZJNxZFrUe0FwAoic\n" + # b"c2kb7ntaiEj5G+qHvykJJro5hy6uLnjiMVbAiJDTAoGAKb67241EmHAXGEwp9sdr\n" + # b"2SMjnIAnQSF39UKAthkYqJxa6elXDQtLoeYdGE7/V+J2K3wIdhoPiuY6b4vD0iX9\n" + # b"JcGM+WntN7YTjX2FsC588JmvbWfnoDHR7HYiPR1E58N597xXdFOzgUgORVr4PMWQ\n" + # b"pqtwaZO3X2WZlvrhr+e46hMCgYBfdIdrm6jYXFjL6RkgUNZJQUTxYGzsY+ZemlNm\n" + # b"fGdQo7a8kePMRuKY2MkcnXPaqTg49YgRmjq4z8CtHokRcWjJUWnPOTs8rmEZUshk\n" + # b"0KJ0mbQdCFt/Uv0mtXgpFTkEZ3DPkDTGcV4oR4CRfOCl0/EU/A5VvL/U4i/mRo7h\n" + # b"ye+xgQKBgD58b+9z+PR5LAJm1tZHIwb4tnyczP28PzwknxFd2qylR4ZNgvAUqGtU\n" + # b"xvpUDpzMioz6zUH9YV43YNtt+5Xnzkqj+u9Mr27/H2v9XPwORGfwQ5XPwRJz/2oC\n" + # b"EnPmP1SZoY9lXKUpQXHXSpDZ2rE2Klt3RHMUMHt8Zpy36E8Vwx8o\n" + # b"-----END RSA PRIVATE KEY-----\n", + # password=None, + # wrapping_algorithm=_WRAPPING_ALGORITHM, + # ) ] diff --git a/test/unit/test_keyring_raw_aes.py b/test/unit/test_keyring_raw_aes.py index b202f805c..85b483b10 100644 --- a/test/unit/test_keyring_raw_aes.py +++ b/test/unit/test_keyring_raw_aes.py @@ -19,11 +19,12 @@ from aws_encryption_sdk.exceptions import GenerateKeyError from aws_encryption_sdk.identifiers import Algorithm, KeyringTraceFlag, WrappingAlgorithm from aws_encryption_sdk.keyring.base import EncryptedDataKey, Keyring -from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring +from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring, generate_data_key from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials from aws_encryption_sdk.structures import KeyringTrace, MasterKeyInfo, RawDataKey from .test_values import VALUES +# from .test_utils import NullRawAESKeyring try: # Python 3.5.0 and 3.5.1 have incompatible typing modules from typing import Iterable # noqa pylint: disable=unused-import @@ -86,6 +87,24 @@ ], ) +_DECRYPTION_MATERIALS_WITH_DATA_KEY = DecryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + data_encryption_key=RawDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + ), + encryption_context=_ENCRYPTION_CONTEXT, + verification_key=b"ex_verification_key", + keyring_trace=[KeyringTrace( + wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} + )] +) + +_DECRYPTION_MATERIALS_WITHOUT_DATA_KEY = DecryptionMaterials( + verification_key=b"ex_verification_key", +) + class TestRawAESKeyring(object): @pytest.fixture(autouse=True) @@ -107,7 +126,7 @@ def test_parent(self): # wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, # wrapping_key=_WRAPPING_KEY, # ) - # assert test.key_provider() == self.mock_encrypted_data_key.key_provider + # assert test.__getattribute__(key_provider) == self.mock_encrypted_data_key.key_provider @patch("aws_encryption_sdk.keyring.raw_keyring.generate_data_key") def test_data_encryption_key_provided(self, mock_generate_data_key): @@ -172,3 +191,53 @@ def test_encrypted_data_key_provided(self, mock_generate_data_key): # ) # test = test_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY) # assert pytest.raises(GenerateKeyError, "Unable to generate data encryption key.") + + @patch("aws_encryption_sdk.keyring.raw_keyring.generate_data_key") + def test_data_key_not_generated(self, mock_generate_data_key): + mock_generate_data_key.return_value = None + test_raw_aes_keyring = RawAESKeyring( + key_namespace=_PROVIDER_ID, + key_name=_KEY_ID, + wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, + wrapping_key=_WRAPPING_KEY, + ) + test = test_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY) + assert pytest.raises(GenerateKeyError) + + @patch("aws_encryption_sdk.internal.crypto.wrapping_keys.WrappingKey.decrypt") + def test_decrypt_when_data_key_provided(self, mock_decrypt): + mock_decrypt.return_value = _DATA_KEY + test_raw_aes_keyring = RawAESKeyring( + key_namespace=_PROVIDER_ID, + key_name=_KEY_ID, + wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, + wrapping_key=_WRAPPING_KEY, + ) + test = test_raw_aes_keyring.on_decrypt(decryption_materials=_DECRYPTION_MATERIALS_WITH_DATA_KEY, + encrypted_data_keys=[self.mock_encrypted_data_key]) + assert not mock_decrypt.called + + # @patch("aws_encryption_sdk.internal.crypto.wrapping_keys.WrappingKey.decrypt") + # def test_decrypt_when_data_key_not_provided(self, mock_decrypt): + # mock_decrypt.return_value = _DATA_KEY + # test_raw_aes_keyring = RawAESKeyring( + # key_namespace=_PROVIDER_ID, + # key_name=_KEY_ID, + # wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, + # wrapping_key=_WRAPPING_KEY, + # ) + # + # test = test_raw_aes_keyring.on_decrypt(decryption_materials=_DECRYPTION_MATERIALS_WITHOUT_DATA_KEY, + # encrypted_data_keys=[ + # EncryptedDataKey( + # key_provider=MasterKeyInfo( + # provider_id=_PROVIDER_ID, + # key_info=_KEY_ID), + # encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\ + # xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" + # b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\ + # x07FzE\xde", + # ) + # ] + # ) + # assert mock_decrypt.called diff --git a/test/unit/test_keyring_raw_rsa.py b/test/unit/test_keyring_raw_rsa.py new file mode 100644 index 000000000..532cfc01e --- /dev/null +++ b/test/unit/test_keyring_raw_rsa.py @@ -0,0 +1,244 @@ +# Copyright 2019 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. +"""Unit tests for Raw AES keyring.""" + +import pytest +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives.asymmetric import rsa +from mock import MagicMock, patch, sentinel + +from aws_encryption_sdk.exceptions import GenerateKeyError +from aws_encryption_sdk.identifiers import Algorithm, KeyringTraceFlag, WrappingAlgorithm +from aws_encryption_sdk.keyring.base import EncryptedDataKey, Keyring +from aws_encryption_sdk.keyring.raw_keyring import RawRSAKeyring, generate_data_key +from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials +from aws_encryption_sdk.structures import KeyringTrace, MasterKeyInfo, RawDataKey + +from .test_values import VALUES +# from .test_utils import NullRawAESKeyring + +try: # Python 3.5.0 and 3.5.1 have incompatible typing modules + from typing import Iterable # noqa pylint: disable=unused-import +except ImportError: # pragma: no cover + # We only actually need these imports when running the mypy checks + pass + +pytestmark = [pytest.mark.unit, pytest.mark.local] + +_ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"} +_PROVIDER_ID = "Random Raw Keys" +_KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" +_WRAPPING_KEY = rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend()) +_SIGNING_KEY = b"aws-crypto-public-key" +_DATA_KEY = ( + b"\x00\xfa\x8c\xdd\x08Au\xc6\x92_4\xc5\xfb\x90\xaf\x8f\xa1D\xaf\xcc\xd25" b"\xa8\x0b\x0b\x16\x92\x91W\x01\xb7\x84" +) +_ENCRYPTION_MATERIALS_WITH_DATA_KEY = EncryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + data_encryption_key=RawDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + ), + encryption_context=_ENCRYPTION_CONTEXT, + signing_key=_SIGNING_KEY, + keyring_trace=[ + KeyringTrace( + wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}, + ) + ], +) + +_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY = EncryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + encryption_context=_ENCRYPTION_CONTEXT, + signing_key=_SIGNING_KEY, +) + +_ENCRYPTION_MATERIALS_WITH_ENCRYPTED_DATA_KEY = EncryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + data_encryption_key=RawDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + ), + encrypted_data_keys=[ + EncryptedDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" + b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", + ) + ], + encryption_context=_ENCRYPTION_CONTEXT, + signing_key=_SIGNING_KEY, + keyring_trace=[ + KeyringTrace( + wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}, + ) + ], +) + +_DECRYPTION_MATERIALS_WITH_DATA_KEY = DecryptionMaterials( + algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, + data_encryption_key=RawDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', + ), + encryption_context=_ENCRYPTION_CONTEXT, + verification_key=b"ex_verification_key", + keyring_trace=[KeyringTrace( + wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} + )] +) + +_DECRYPTION_MATERIALS_WITHOUT_DATA_KEY = DecryptionMaterials( + verification_key=b"ex_verification_key", +) + + +class TestRawRSAKeyring(object): + @pytest.fixture(autouse=True) + def apply_fixtures(self): + self.mock_encrypted_data_key = EncryptedDataKey( + key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), + encrypted_data_key=VALUES["encrypted_data_key"], + ) + self.mock_encryption_materials = MagicMock() + self.mock_encryption_materials.__class__ = EncryptionMaterials + + def test_parent(self): + assert issubclass(RawRSAKeyring, Keyring) + + # def test_initialization(self): + # test = RawAESKeyring( + # key_namespace=_PROVIDER_ID, + # key_name=_KEY_ID, + # wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, + # wrapping_key=_WRAPPING_KEY, + # ) + # assert test.__getattribute__(key_provider) == self.mock_encrypted_data_key.key_provider + + @patch("aws_encryption_sdk.keyring.raw_keyring.generate_data_key") + def test_data_encryption_key_provided(self, mock_generate_data_key): + mock_generate_data_key.return_value = _DATA_KEY + test_raw_rsa_keyring = RawRSAKeyring( + key_namespace=_PROVIDER_ID, + key_name=_KEY_ID, + wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, + wrapping_key=_WRAPPING_KEY, + ) + + test = test_raw_rsa_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITH_DATA_KEY) + # Check if keyring is generated + assert not mock_generate_data_key.called + + # Check if data encryption key is encrypted + assert test.encrypted_data_keys is not None + + def test_data_encryption_key_generated(self): + test_raw_rsa_keyring = RawRSAKeyring( + key_namespace=_PROVIDER_ID, + key_name=_KEY_ID, + wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, + wrapping_key=_WRAPPING_KEY, + ) + test = test_raw_rsa_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY) + + # Check if key is generated + if not test.data_encryption_key: + # Check if error thrown if data key is not generated + assert pytest.raises(GenerateKeyError, "Unable to generate data encryption key.") + else: + # Check if data key is generated + assert test.data_encryption_key and test.data_encryption_key is not None + assert test.encrypted_data_keys and test.encrypted_data_keys is not None + + @patch("aws_encryption_sdk.keyring.raw_keyring.generate_data_key") + def test_encrypted_data_key_provided(self, mock_generate_data_key): + mock_generate_data_key.return_value = _DATA_KEY + test_raw_rsa_keyring = RawRSAKeyring( + key_namespace=_PROVIDER_ID, + key_name=_KEY_ID, + wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, + wrapping_key=_WRAPPING_KEY, + ) + test = test_raw_rsa_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITH_ENCRYPTED_DATA_KEY) + + # Check if generate_data_key is called + assert not mock_generate_data_key.called + # + # Check if encrypt is called + assert len(test.encrypted_data_keys) == len(_ENCRYPTION_MATERIALS_WITH_ENCRYPTED_DATA_KEY.encrypted_data_keys) + + # @patch("aws_encryption_sdk.key_providers.raw.os.urandom") + # def test_data_key_not_generated(self, mock_os_urandom): + # mock_os_urandom.return_value = None + # test_raw_aes_keyring = RawAESKeyring( + # key_namespace=_PROVIDER_ID, + # key_name=_KEY_ID, + # wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, + # wrapping_key=_WRAPPING_KEY, + # ) + # test = test_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY) + # assert pytest.raises(GenerateKeyError, "Unable to generate data encryption key.") + + @patch("aws_encryption_sdk.keyring.raw_keyring.generate_data_key") + def test_data_key_not_generated(self, mock_generate_data_key): + mock_generate_data_key.return_value = None + test_raw_rsa_keyring = RawRSAKeyring( + key_namespace=_PROVIDER_ID, + key_name=_KEY_ID, + wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, + wrapping_key=_WRAPPING_KEY, + ) + test = test_raw_rsa_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY) + assert pytest.raises(GenerateKeyError) + + @patch("aws_encryption_sdk.internal.crypto.wrapping_keys.WrappingKey.decrypt") + def test_decrypt_when_data_key_provided(self, mock_decrypt): + mock_decrypt.return_value = _DATA_KEY + test_raw_rsa_keyring = RawRSAKeyring( + key_namespace=_PROVIDER_ID, + key_name=_KEY_ID, + wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, + wrapping_key=_WRAPPING_KEY, + ) + test = test_raw_rsa_keyring.on_decrypt(decryption_materials=_DECRYPTION_MATERIALS_WITH_DATA_KEY, + encrypted_data_keys=[self.mock_encrypted_data_key]) + assert not mock_decrypt.called + + # @patch("aws_encryption_sdk.internal.crypto.wrapping_keys.WrappingKey.decrypt") + # def test_decrypt_when_data_key_not_provided(self, mock_decrypt): + # mock_decrypt.return_value = _DATA_KEY + # test_raw_aes_keyring = RawAESKeyring( + # key_namespace=_PROVIDER_ID, + # key_name=_KEY_ID, + # wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, + # wrapping_key=_WRAPPING_KEY, + # ) + # + # test = test_raw_aes_keyring.on_decrypt(decryption_materials=_DECRYPTION_MATERIALS_WITHOUT_DATA_KEY, + # encrypted_data_keys=[ + # EncryptedDataKey( + # key_provider=MasterKeyInfo( + # provider_id=_PROVIDER_ID, + # key_info=_KEY_ID), + # encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\ + # xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" + # b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\ + # x07FzE\xde", + # ) + # ] + # ) + # assert mock_decrypt.called diff --git a/test/unit/test_utils.py b/test/unit/test_utils.py index b1374a09d..0da12a869 100644 --- a/test/unit/test_utils.py +++ b/test/unit/test_utils.py @@ -21,11 +21,19 @@ import aws_encryption_sdk.internal.utils from aws_encryption_sdk.exceptions import InvalidDataKeyError, SerializationError, UnknownIdentityError from aws_encryption_sdk.internal.defaults import MAX_FRAME_SIZE, MESSAGE_ID_LENGTH +from aws_encryption_sdk.materials_managers import EncryptionMaterials, DecryptionMaterials, EncryptedDataKey from aws_encryption_sdk.structures import DataKey, EncryptedDataKey, MasterKeyInfo, RawDataKey +from aws_encryption_sdk.keyring.raw_keyring import RawRSAKeyring, RawAESKeyring from .test_values import VALUES from .unit_test_utils import assert_prepped_stream_identity +try: # Python 3.5.0 and 3.5.1 have incompatible typing modules + from typing import Iterable, Union # noqa pylint: disable=unused-import +except ImportError: # pragma: no cover + # We only actually need these imports when running the mypy checks + pass + pytestmark = [pytest.mark.unit, pytest.mark.local] @@ -42,6 +50,24 @@ def test_prep_stream_data_wrap(source): assert_prepped_stream_identity(test, io.BytesIO) +class NullRawRSAKeyring(RawRSAKeyring): + def on_encrypt(self, encryption_materials): + # type: (EncryptionMaterials) -> EncryptionMaterials + return encryption_materials + + def on_decrypt(self, decryption_materials, encrypted_data_keys): + # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials + return decryption_materials + + +class NullRawAESKeyring(RawAESKeyring): + def on_encrypt(self): + return + + def on_decrypt(self): + return + + class TestUtils(object): @pytest.fixture(autouse=True) def apply_fixtures(self): @@ -265,3 +291,4 @@ def test_source_data_key_length_check_invalid(self): source_data_key=mock_data_key, algorithm=mock_algorithm ) excinfo.match("Invalid Source Data Key length 4 for algorithm required: 5") + From 41dd1408e6b7c741a5fb1ee4567d2b915a2310d9 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Mon, 22 Jul 2019 14:30:35 -0700 Subject: [PATCH 095/110] Changes for PEM encoding --- test/functional/test_f_keyring_raw_rsa.py | 53 +++++++++++------------ test/unit/test_values.py | 48 ++++++++++++++++++++ 2 files changed, 74 insertions(+), 27 deletions(-) diff --git a/test/functional/test_f_keyring_raw_rsa.py b/test/functional/test_f_keyring_raw_rsa.py index 7b39e01e0..0ce72b23c 100644 --- a/test/functional/test_f_keyring_raw_rsa.py +++ b/test/functional/test_f_keyring_raw_rsa.py @@ -28,6 +28,22 @@ _KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" _SIGNING_KEY = b"aws-crypto-public-key" _WRAPPING_ALGORITHM = WrappingAlgorithm.RSA_OAEP_SHA256_MGF1 +_PRIVATE_KEY = b"-----BEGIN RSA PRIVATE KEY-----"\ + b"MIICXgIBAAKBgQCUjhI8YRPXV8Gfofbg/"\ + b"PLjWw2AzowQTPErLU2z3+xGqElMdzdiC4Ta43DFWZg34Eg0X8kQPAeoe8h3cRSMo"\ + b"77eSOHt2dPo7OfTfZqsH8766fivHIKVxBYPX8SZYIUhMtRnlg3uqch9BksfRop+h"\ + b"f8h/H3lfervJoevS2CXYB9/iwIDAQABAoGBAIqeGzQOHbaGI51yQ2zjez1dPDdiB"\ + b"F49fZideHEM1GuGIodgguRQ/VJGgncUSC5zcMy2SGaGrVqwznltohAtxy4rZp0eh"\ + b"2O3aHYi9Wehd0SPLh+qwu7mJDuh0z15hmCOue070FnUtyuSwhXLwDrbot2+5HbmF"\ + b"9clJLI5tv92gvIpAkEA+Bv5i8XJNPN1rao31aQFoi9bFIOEclk3b1RbLX6mpZBFS"\ + b"U9CNUy0RQNC0+H3KZ5CTvsyFGpMfTdiFc/Qdesk3QJBAJlHjrvoadP+PU3zXYrWR"\ + b"D5EryyTxaP1bOjrp9xLuQBeU8x7EVJdpoul9OmwcT3NrAqvxDE9okjha2tjCI6O2"\ + b"4cCQQDMyOJPYL/zaaPO5LlTKB/SPv4RT4BplYPw6xKa2XeZHhxiJv5B2f7NG6T0G"\ + b"AWWn16hrCoouZhKngTidfXc7motAkA/KiTgvKr3yHp86AAxWZDv1CAYD6FPqrDB3"\ + b"3LiLnZDd5uy1ThTJ/Kc87vUnXhdDqeKE9qWrB53SCWbMElzbd17AkEA4DMp+6ngM"\ + b"o6sS0dY1X6nTLqgvK3B0z5GCAdSEy3Y8jh995Lrl+hy88HzuwUkQwwPlZkFhUNCx"\ + b"edrC6cTKE5xLA=="\ + b"-----END RSA PRIVATE KEY-----" _ENCRYPTION_MATERIALS = [ EncryptionMaterials( @@ -84,30 +100,13 @@ wrapping_key=rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend()), wrapping_algorithm=_WRAPPING_ALGORITHM, ), - # RawRSAKeyring.fromPEMEncoding( - # key_namespace=_PROVIDER_ID, - # key_name=_KEY_ID, - # encoded_key=( - # b"-----BEGIN RSA PRIVATE KEY-----" - # b"MIICXgIBAAKBgQCUjhI8YRPXV8Gfofbg/" - # b"PLjWw2AzowQTPErLU2z3+xGqElMdzdiC4Ta43DFWZg34Eg0X8kQPAeoe8h3cRSMo" - # b"77eSOHt2dPo7OfTfZqsH8766fivHIKVxBYPX8SZYIUhMtRnlg3uqch9BksfRop+h" - # b"f8h/H3lfervJoevS2CXYB9/iwIDAQABAoGBAIqeGzQOHbaGI51yQ2zjez1dPDdiB" - # b"F49fZideHEM1GuGIodgguRQ/VJGgncUSC5zcMy2SGaGrVqwznltohAtxy4rZp0eh" - # b"2O3aHYi9Wehd0SPLh+qwu7mJDuh0z15hmCOue070FnUtyuSwhXLwDrbot2+5HbmF" - # b"9clJLI5tv92gvIpAkEA+Bv5i8XJNPN1rao31aQFoi9bFIOEclk3b1RbLX6mpZBFS" - # b"U9CNUy0RQNC0+H3KZ5CTvsyFGpMfTdiFc/Qdesk3QJBAJlHjrvoadP+PU3zXYrWR" - # b"D5EryyTxaP1bOjrp9xLuQBeU8x7EVJdpoul9OmwcT3NrAqvxDE9okjha2tjCI6O2" - # b"4cCQQDMyOJPYL/zaaPO5LlTKB/SPv4RT4BplYPw6xKa2XeZHhxiJv5B2f7NG6T0G" - # b"AWWn16hrCoouZhKngTidfXc7motAkA/KiTgvKr3yHp86AAxWZDv1CAYD6FPqrDB3" - # b"3LiLnZDd5uy1ThTJ/Kc87vUnXhdDqeKE9qWrB53SCWbMElzbd17AkEA4DMp+6ngM" - # b"o6sS0dY1X6nTLqgvK3B0z5GCAdSEy3Y8jh995Lrl+hy88HzuwUkQwwPlZkFhUNCx" - # b"edrC6cTKE5xLA==" - # b"-----END RSA PRIVATE KEY-----" - # ), - # password=None, - # wrapping_algorithm=_WRAPPING_ALGORITHM, - # ), + RawRSAKeyring.fromPEMEncoding( + key_namespace=_PROVIDER_ID, + key_name=_KEY_ID, + encoded_key=_PRIVATE_KEY, + password=None, + wrapping_algorithm=_WRAPPING_ALGORITHM, + ), # RawRSAKeyring.fromDEREncoding( # key_namespace=_PROVIDER_ID, # key_name=_KEY_ID, @@ -161,6 +160,6 @@ def test_raw_rsa_encryption_decryption(encryption_materials_samples, fake_raw_rs decryption_materials=decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys ) - if decryption_materials.data_encryption_key: - # Check if the data keys match - assert encryption_materials.data_encryption_key == decryption_materials.data_encryption_key + # if decryption_materials.data_encryption_key: + # # Check if the data keys match + assert encryption_materials.data_encryption_key == decryption_materials.data_encryption_key diff --git a/test/unit/test_values.py b/test/unit/test_values.py index 26eff1341..acd09db2a 100644 --- a/test/unit/test_values.py +++ b/test/unit/test_values.py @@ -187,6 +187,54 @@ def array_byte(source): "\xff\x8fn\x95\xf0\xf0E\x91Uj\xb0E3=\x0e\x1a\xf1'4\xf6" ), "signature_len": b"\x00h", + "private_rsa_key_bytes": [ + ( + b"-----BEGIN RSA PRIVATE KEY-----"b"MIICXgIBAAKBgQCUjhI8YRPXV8Gfofbg/" + b"PLjWw2AzowQTPErLU2z3+xGqElMdzdiC4Ta43DFWZg34Eg0X8kQPAeoe8h3cRSMo" + b"77eSOHt2dPo7OfTfZqsH8766fivHIKVxBYPX8SZYIUhMtRnlg3uqch9BksfRop+h" + b"f8h/H3lfervJoevS2CXYB9/iwIDAQABAoGBAIqeGzQOHbaGI51yQ2zjez1dPDdiB" + b"F49fZideHEM1GuGIodgguRQ/VJGgncUSC5zcMy2SGaGrVqwznltohAtxy4rZp0eh" + b"2O3aHYi9Wehd0SPLh+qwu7mJDuh0z15hmCOue070FnUtyuSwhXLwDrbot2+5HbmF" + b"9clJLI5tv92gvIpAkEA+Bv5i8XJNPN1rao31aQFoi9bFIOEclk3b1RbLX6mpZBFS" + b"U9CNUy0RQNC0+H3KZ5CTvsyFGpMfTdiFc/Qdesk3QJBAJlHjrvoadP+PU3zXYrWR" + b"D5EryyTxaP1bOjrp9xLuQBeU8x7EVJdpoul9OmwcT3NrAqvxDE9okjha2tjCI6O2" + b"4cCQQDMyOJPYL/zaaPO5LlTKB/SPv4RT4BplYPw6xKa2XeZHhxiJv5B2f7NG6T0G" + b"AWWn16hrCoouZhKngTidfXc7motAkA/KiTgvKr3yHp86AAxWZDv1CAYD6FPqrDB3" + b"3LiLnZDd5uy1ThTJ/Kc87vUnXhdDqeKE9qWrB53SCWbMElzbd17AkEA4DMp+6ngM" + b"o6sS0dY1X6nTLqgvK3B0z5GCAdSEy3Y8jh995Lrl+hy88HzuwUkQwwPlZkFhUNCx" + b"edrC6cTKE5xLA==" + b"-----END RSA PRIVATE KEY-----" + ), + ( + b"-----BEGIN RSA PRIVATE KEY-----\n" + b"MIIEowIBAAKCAQEAo8uCyhiO4JUGZV+rtNq5DBA9Lm4xkw5kTA3v6EPybs8bVXL2\n" + b"ZE6jkbo+xT4Jg/bKzUpnp1fE+T1ruGPtsPdoEmhY/P64LDNIs3sRq5U4QV9IETU1\n" + b"vIcbNNkgGhRjV8J87YNY0tV0H7tuWuZRpqnS+gjV6V9lUMkbvjMCc5IBqQc3heut\n" + b"/+fH4JwpGlGxOVXI8QAapnSy1XpCr3+PT29kydVJnIMuAoFrurojRpOQbOuVvhtA\n" + b"gARhst1Ji4nfROGYkj6eZhvkz2Bkud4/+3lGvVU5LO1vD8oY7WoGtpin3h50VcWe\n" + b"aBT4kejx4s9/G9C4R24lTH09J9HO2UUsuCqZYQIDAQABAoIBAQCfC90bCk+qaWqF\n" + b"gymC+qOWwCn4bM28gswHQb1D5r6AtKBRD8mKywVvWs7azguFVV3Fi8sspkBA2FBC\n" + b"At5p6ULoJOTL/TauzLl6djVJTCMM701WUDm2r+ZOIctXJ5bzP4n5Q4I7b0NMEL7u\n" + b"ixib4elYGr5D1vrVQAKtZHCr8gmkqyx8Mz7wkJepzBP9EeVzETCHsmiQDd5WYlO1\n" + b"C2IQYgw6MJzgM4entJ0V/GPytkodblGY95ORVK7ZhyNtda+r5BZ6/jeMW+hA3VoK\n" + b"tHSWjHt06ueVCCieZIATmYzBNt+zEz5UA2l7ksg3eWfVORJQS7a6Ef4VvbJLM9Ca\n" + b"m1kdsjelAoGBANKgvRf39i3bSuvm5VoyJuqinSb/23IH3Zo7XOZ5G164vh49E9Cq\n" + b"dOXXVxox74ppj/kbGUoOk+AvaB48zzfzNvac0a7lRHExykPH2kVrI/NwH/1OcT/x\n" + b"2e2DnFYocXcb4gbdZQ+m6X3zkxOYcONRzPVW1uMrFTWHcJveMUm4PGx7AoGBAMcU\n" + b"IRvrT6ye5se0s27gHnPweV+3xjsNtXZcK82N7duXyHmNjxrwOAv0SOhUmTkRXArM\n" + b"6aN5D8vyZBSWma2TgUKwpQYFTI+4Sp7sdkkyojGAEixJ+c5TZJNxZFrUe0FwAoic\n" + b"c2kb7ntaiEj5G+qHvykJJro5hy6uLnjiMVbAiJDTAoGAKb67241EmHAXGEwp9sdr\n" + b"2SMjnIAnQSF39UKAthkYqJxa6elXDQtLoeYdGE7/V+J2K3wIdhoPiuY6b4vD0iX9\n" + b"JcGM+WntN7YTjX2FsC588JmvbWfnoDHR7HYiPR1E58N597xXdFOzgUgORVr4PMWQ\n" + b"pqtwaZO3X2WZlvrhr+e46hMCgYBfdIdrm6jYXFjL6RkgUNZJQUTxYGzsY+ZemlNm\n" + b"fGdQo7a8kePMRuKY2MkcnXPaqTg49YgRmjq4z8CtHokRcWjJUWnPOTs8rmEZUshk\n" + b"0KJ0mbQdCFt/Uv0mtXgpFTkEZ3DPkDTGcV4oR4CRfOCl0/EU/A5VvL/U4i/mRo7h\n" + b"ye+xgQKBgD58b+9z+PR5LAJm1tZHIwb4tnyczP28PzwknxFd2qylR4ZNgvAUqGtU\n" + b"xvpUDpzMioz6zUH9YV43YNtt+5Xnzkqj+u9Mr27/H2v9XPwORGfwQ5XPwRJz/2oC\n" + b"EnPmP1SZoY9lXKUpQXHXSpDZ2rE2Klt3RHMUMHt8Zpy36E8Vwx8o\n" + b"-----END RSA PRIVATE KEY-----\n" + ) + ] } VALUES["updated_encryption_context"] = copy.deepcopy(VALUES["encryption_context"]) VALUES["updated_encryption_context"]["aws-crypto-public-key"] = VALUES["encoded_curve_point"] From b350207745742611a18f7e321c75465af91644ce Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 23 Jul 2019 12:53:39 -0700 Subject: [PATCH 096/110] Changed base API to remove metaclass and modified tests --- src/aws_encryption_sdk/keyring/base.py | 7 ------- test/unit/test_keyring_base.py | 14 ++++---------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index f253ce500..770b53c0b 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -11,10 +11,6 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Base class interface for Keyrings.""" -import abc - -import six - from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials from aws_encryption_sdk.structures import EncryptedDataKey @@ -25,14 +21,12 @@ pass -@six.add_metaclass(abc.ABCMeta) class Keyring(object): """Parent interface for Keyring classes. .. versionadded:: 1.5.0 """ - @abc.abstractmethod def on_encrypt(self, encryption_materials): # type: (EncryptionMaterials) -> EncryptionMaterials """Generate a data key if not present and encrypt it using any available wrapping key. @@ -45,7 +39,6 @@ def on_encrypt(self, encryption_materials): """ raise NotImplementedError("Keyring does not implement on_encrypt function") - @abc.abstractmethod def on_decrypt(self, decryption_materials, encrypted_data_keys): # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials """Attempt to decrypt the encrypted data keys. diff --git a/test/unit/test_keyring_base.py b/test/unit/test_keyring_base.py index 02ebc0a98..6f40dc794 100644 --- a/test/unit/test_keyring_base.py +++ b/test/unit/test_keyring_base.py @@ -60,20 +60,14 @@ def test_keyring_no_encrypt(): class KeyringNoEncrypt(Keyring): def on_decrypt(self, _decryption_materials, _encrypted_data_keys): - # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials - return _decryption_materials + return - with pytest.raises(TypeError) as exc_info: - KeyringNoEncrypt() - exc_info.match("Can't instantiate abstract class KeyringNoEncrypt with abstract methods on_encrypt") + assert pytest.raises(NotImplementedError) def test_keyring_no_decrypt(): class KeyringNoDecrypt(Keyring): def on_encrypt(self, _encryption_materials): - # type: (EncryptionMaterials) -> EncryptionMaterials - return _encryption_materials + return - with pytest.raises(TypeError) as exc_info: - KeyringNoDecrypt() - exc_info.match("Can't instantiate abstract class KeyringNoDecrypt with abstract methods on_decrypt") + assert pytest.raises(NotImplementedError) From 9de5b164e5b9c56af0ee3272402a1463bc8343de Mon Sep 17 00:00:00 2001 From: MeghaShetty Date: Tue, 23 Jul 2019 14:39:20 -0700 Subject: [PATCH 097/110] Delete raw_keyring.py --- src/aws_encryption_sdk/keyring/raw_keyring.py | 394 ------------------ 1 file changed, 394 deletions(-) delete mode 100644 src/aws_encryption_sdk/keyring/raw_keyring.py diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py deleted file mode 100644 index 3cfdf9c21..000000000 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ /dev/null @@ -1,394 +0,0 @@ -# Copyright 2017 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. -"""Resources required for Raw Keyrings.""" - -import logging -import os - -import attr -import six -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives import serialization -from cryptography.hazmat.primitives.asymmetric import padding, rsa - -from aws_encryption_sdk.exceptions import GenerateKeyError -from aws_encryption_sdk.identifiers import EncryptionKeyType, KeyringTraceFlag, 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.keyring.base import Keyring -from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials -from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey - -try: # Python 3.5.0 and 3.5.1 have incompatible typing modules - from typing import Iterable, Union # noqa pylint: disable=unused-import -except ImportError: # pragma: no cover - # We only actually need these imports when running the mypy checks - pass - - -def get_key_info_prefix(key_namespace, key_name, wrapping_key): - # type: (str, bytes, WrappingKey) -> six.binary_type - """Helper function to get key info prefix - - :param str key_namespace: String defining the keyring. - :param bytes key_name: Key ID - :param wrapping_key: Encryption key with which to wrap plaintext data key. - :type wrapping_key: WrappingKey - :return: Serialized key_info prefix - :rtype: bytes - """ - key_info_prefix = serialize_raw_master_key_prefix( - RawMasterKey(provider_id=key_namespace, key_id=key_name, wrapping_key=wrapping_key) - ) - return key_info_prefix - - -def generate_data_key( - encryption_materials, # type: EncryptionMaterials - key_provider, # type: MasterKeyInfo -): - # type: (...) -> bytes - """Generates plaintext data key for the keyring. - - :param encryption_materials: Encryption materials for the keyring to modify. - :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials - :param key_provider: Information about the key in the keyring. - :type key_provider: MasterKeyInfo - :return bytes: Plaintext data key - """ - # Generate data key - plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) - - # Check if data key is generated - if not plaintext_data_key or plaintext_data_key is None: - raise GenerateKeyError("Unable to generate data encryption key.") - - # Create a keyring trace - keyring_trace = KeyringTrace(wrapping_key=key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}) - - # plaintext_data_key to RawDataKey - data_encryption_key = RawDataKey(key_provider=key_provider, data_key=plaintext_data_key) - - # Add generated data key to encryption_materials - encryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) - - return plaintext_data_key - - -@attr.s -class RawAESKeyring(Keyring): - """Public class for Raw AES Keyring. - - :param str key_namespace: String defining the keyring. - :param bytes key_name: Key ID - :param bytes wrapping_key: Encryption key with which to wrap plaintext data key. - :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key. - :type wrapping_algorithm: WrappingAlgorithm - """ - - key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) - key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) - _wrapping_key = attr.ib(repr=False, validator=attr.validators.instance_of(six.binary_type)) - _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) - - def __attrs_post_init__(self): - # type: () -> None - """Prepares initial values not handled by attrs.""" - self._key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name) - - self._wrapping_key_structure = WrappingKey( - wrapping_algorithm=self._wrapping_algorithm, - wrapping_key=self._wrapping_key, - wrapping_key_type=EncryptionKeyType.SYMMETRIC, - ) - - self._key_info_prefix = get_key_info_prefix( - key_namespace=self.key_namespace, key_name=self.key_name, wrapping_key=self._wrapping_key_structure - ) - - def on_encrypt(self, encryption_materials): - # type: (EncryptionMaterials) -> EncryptionMaterials - """Generate a data key if not present and encrypt it using any available wrapping key - - :param encryption_materials: Encryption materials for the keyring to modify - :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials - :returns: Optionally modified encryption materials - :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials - """ - if not encryption_materials.data_encryption_key: - plaintext_data_key = generate_data_key( - encryption_materials=encryption_materials, key_provider=self._key_provider - ) - else: - plaintext_data_key = encryption_materials.data_encryption_key.data_key - - # Check if data key exists - if not plaintext_data_key or plaintext_data_key is None: - raise GenerateKeyError("Unable to generate data encryption key.") - - # Encrypt data key - encrypted_wrapped_key = self._wrapping_key_structure.encrypt( - plaintext_data_key=plaintext_data_key, encryption_context=encryption_materials.encryption_context - ) - - # EncryptedData to EncryptedDataKey - encrypted_data_key = serialize_wrapped_key( - key_provider=self._key_provider, - wrapping_algorithm=self._wrapping_algorithm, - wrapping_key_id=self.key_name, - encrypted_wrapped_key=encrypted_wrapped_key, - ) - - # Update Keyring Trace - if encrypted_data_key: - keyring_trace = KeyringTrace( - wrapping_key=encrypted_data_key.key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY} - ) - - # Add encrypted data key to encryption_materials - encryption_materials.add_encrypted_data_key( - encrypted_data_key=encrypted_data_key, keyring_trace=keyring_trace - ) - return encryption_materials - - def on_decrypt(self, decryption_materials, encrypted_data_keys): - # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials - """Attempt to decrypt the encrypted data keys. - - :param decryption_materials: Decryption materials for the keyring to modify - :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials - :param encrypted_data_keys: List of encrypted data keys - :type: List of `aws_encryption_sdk.structures.EncryptedDataKey` - :returns: Optionally modified decryption materials - :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials - """ - if decryption_materials.data_encryption_key: - return decryption_materials - - # Decrypt data key - expected_key_info_len = len(self._key_info_prefix) + self._wrapping_algorithm.algorithm.iv_len - for key in encrypted_data_keys: - if ( - key.key_provider.provider_id == self._key_provider.provider_id - and len(key.key_provider.key_info) == expected_key_info_len - and key.key_provider.key_info.startswith(self._key_info_prefix) - ): - # Wrapped EncryptedDataKey to deserialized EncryptedData - encrypted_wrapped_key = deserialize_wrapped_key( - wrapping_algorithm=self._wrapping_algorithm, - wrapping_key_id=self.key_name, - wrapped_encrypted_key=key, - ) - # EncryptedData to raw key string - try: - plaintext_data_key = self._wrapping_key_structure.decrypt( - encrypted_wrapped_data_key=encrypted_wrapped_key, - encryption_context=decryption_materials.encryption_context, - ) - - except Exception as error: # pylint: disable=broad-except - logger = logging.getLogger(__name__) - logger.error(error.__class__.__name__, ":", str(error)) - return decryption_materials - - if plaintext_data_key: - # Create a keyring trace - keyring_trace = KeyringTrace( - wrapping_key=self._key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} - ) - - # Update decryption materials - data_encryption_key = RawDataKey( - key_provider=MasterKeyInfo(provider_id=self._key_provider.provider_id, key_info=self.key_name), - data_key=plaintext_data_key, - ) - decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) - - if decryption_materials.data_encryption_key: - return decryption_materials - - return decryption_materials - - -@attr.s -class RawRSAKeyring(Keyring): - """Public class for Raw RSA Keyring. - - :param str key_namespace: String defining the keyring ID - :param bytes key_name: Key ID - :param wrapping_key: Encryption key with which to wrap plaintext data key - :type wrapping_key: object - :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key - :type wrapping_algorithm: WrappingAlgorithm - :param key_provider: Complete information about the key in the keyring - :type key_provider: MasterKeyInfo - """ - - key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) - key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) - # _wrapping_key = attr.ib(repr=False, validator=attr.validators.in_([rsa.RSAPrivateKey, rsa.RSAPublicKey])) - # ----- need to figure out how to do this correctly - _wrapping_key = attr.ib(repr=False, validator=attr.validators.instance_of(object)) - _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) - - @classmethod - def fromPEMEncoding(cls, key_namespace, key_name, encoded_key, password, wrapping_algorithm): - # key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) - # key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) - # _encoded_key = attr.ib(validator=attr.validators.instance_of(six.binary_type)) - # _password = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(six.binary_type))) - # _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) - if password: - loaded_wrapping_key = serialization.load_pem_private_key( - data=encoded_key, password=password, backend=default_backend() - ) - else: - loaded_wrapping_key = serialization.load_pem_public_key(data=encoded_key, backend=default_backend()) - return cls( - key_namespace=key_namespace, - key_name=key_name, - wrapping_key=loaded_wrapping_key, - wrapping_algorithm=wrapping_algorithm, - ) - - @classmethod - def fromDEREncoding(cls, key_namespace, key_name, encoded_key, password, wrapping_algorithm): - # key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) - # key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) - # _encoded_key = attr.ib(validator=attr.validators.instance_of(six.binary_type)) - # _password = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(six.binary_type))) - # _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) - if password: - loaded_wrapping_key = serialization.load_der_private_key( - data=encoded_key, password=password, backend=default_backend() - ) - else: - loaded_wrapping_key = serialization.load_der_public_key(data=encoded_key, backend=default_backend()) - return cls( - key_namespace=key_namespace, - key_name=key_name, - wrapping_key=loaded_wrapping_key, - wrapping_algorithm=wrapping_algorithm, - ) - - def __attrs_post_init__(self): - # type: () -> None - """Prepares initial values not handled by attrs.""" - self._key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name) - - def on_encrypt(self, encryption_materials): - # type: (EncryptionMaterials) -> EncryptionMaterials - """Generate a data key if not present and encrypt it using any available wrapping key. - - :param encryption_materials: Encryption materials for the keyring to modify. - :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials - :returns: Optionally modified encryption materials. - :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials - """ - if not encryption_materials.data_encryption_key: - plaintext_data_key = generate_data_key( - encryption_materials=encryption_materials, key_provider=self._key_provider - ) - else: - plaintext_data_key = encryption_materials.data_encryption_key.data_key - if isinstance(self._wrapping_key, rsa.RSAPublicKey): - - # Encrypt data key - encrypted_wrapped_key = EncryptedData( - iv=None, - ciphertext=self._wrapping_key.encrypt( - plaintext=plaintext_data_key, padding=self._wrapping_algorithm.padding - ), - tag=None, - ) - else: - # Encrypt data key - encrypted_wrapped_key = EncryptedData( - iv=None, - ciphertext=self._wrapping_key.public_key().encrypt( - plaintext=plaintext_data_key, padding=self._wrapping_algorithm.padding - ), - tag=None, - ) - - # EncryptedData to EncryptedDataKey - encrypted_data_key = serialize_wrapped_key( - key_provider=self._key_provider, - wrapping_algorithm=self._wrapping_algorithm, - wrapping_key_id=self.key_name, - encrypted_wrapped_key=encrypted_wrapped_key, - ) - - # Update Keyring Trace - if encrypted_data_key: - keyring_trace = KeyringTrace( - wrapping_key=encrypted_data_key.key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY} - ) - - # Add encrypted data key to encryption_materials - encryption_materials.add_encrypted_data_key( - encrypted_data_key=encrypted_data_key, keyring_trace=keyring_trace - ) - - return encryption_materials - - def on_decrypt(self, decryption_materials, encrypted_data_keys): - # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials - """Attempt to decrypt the encrypted data keys. - - :param decryption_materials: Decryption materials for the keyring to modify. - :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials - :param encrypted_data_keys: List of encrypted data keys. - :type: List of `aws_encryption_sdk.structures.EncryptedDataKey` - :returns: Optionally modified decryption materials. - :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials - """ - if isinstance(self._wrapping_key, rsa.RSAPrivateKey): - # Decrypt data key - for key in encrypted_data_keys: - if key.key_provider == self._key_provider: - # Wrapped EncryptedDataKey to deserialized EncryptedData - encrypted_wrapped_key = deserialize_wrapped_key( - wrapping_algorithm=self._wrapping_algorithm, - wrapping_key_id=self.key_name, - wrapped_encrypted_key=key, - ) - try: - plaintext_data_key = self._wrapping_key.decrypt( - ciphertext=encrypted_wrapped_key.ciphertext, padding=self._wrapping_algorithm.padding - ) - except Exception as error: # pylint: disable=broad-except - logger = logging.getLogger() - logger.error(error.__class__.__name__, ":", str(error)) - return decryption_materials - - if plaintext_data_key: - # Create a keyring trace - keyring_trace = KeyringTrace( - wrapping_key=self._key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} - ) - - # Update decryption materials - data_encryption_key = RawDataKey( - key_provider=MasterKeyInfo( - provider_id=self._key_provider.provider_id, key_info=self.key_name - ), - data_key=plaintext_data_key, - ) - decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) - if decryption_materials.data_encryption_key: - return decryption_materials - - return decryption_materials From 16d433d46453e03344de2369f966c8e4110d41c6 Mon Sep 17 00:00:00 2001 From: MeghaShetty Date: Tue, 23 Jul 2019 14:39:42 -0700 Subject: [PATCH 098/110] Delete test_f_keyring_raw_aes.py --- test/functional/test_f_keyring_raw_aes.py | 113 ---------------------- 1 file changed, 113 deletions(-) delete mode 100644 test/functional/test_f_keyring_raw_aes.py diff --git a/test/functional/test_f_keyring_raw_aes.py b/test/functional/test_f_keyring_raw_aes.py deleted file mode 100644 index 18c0638bc..000000000 --- a/test/functional/test_f_keyring_raw_aes.py +++ /dev/null @@ -1,113 +0,0 @@ -# Copyright 2019 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. -"""Functional tests for Raw AES keyring encryption decryption path.""" - -import pytest - -from aws_encryption_sdk.identifiers import Algorithm, KeyringTraceFlag, WrappingAlgorithm -from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring -from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials -from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey - -pytestmark = [pytest.mark.functional, pytest.mark.local] - -_ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"} -_PROVIDER_ID = "Random Raw Keys" -_KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" -_WRAPPING_KEY = b"12345678901234567890123456789012" -_SIGNING_KEY = b"aws-crypto-public-key" - -_ENCRYPTION_MATERIALS = [ - EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - ), - EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - keyring_trace=[ - KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}, - ) - ], - ), - EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encrypted_data_keys=[ - EncryptedDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" - b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", - ) - ], - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - keyring_trace=[ - KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={ - KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, - KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY, - }, - ) - ], - ), -] - - -@pytest.mark.parametrize("encryption_materials_samples", _ENCRYPTION_MATERIALS) -def test_raw_aes_encryption_decryption(encryption_materials_samples): - - # Initializing attributes - key_namespace = _PROVIDER_ID - key_name = _KEY_ID - _wrapping_algorithm = WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING - - # Creating an instance of a raw AES keyring - fake_raw_aes_keyring = RawAESKeyring( - key_namespace=key_namespace, - key_name=key_name, - wrapping_key=_WRAPPING_KEY, - wrapping_algorithm=_wrapping_algorithm, - ) - - # Call on_encrypt function for the keyring - encryption_materials = fake_raw_aes_keyring.on_encrypt(encryption_materials=encryption_materials_samples) - - print("PLAINTEXT DATA KEY") - print(encryption_materials.data_encryption_key) - - # Generate decryption materials - decryption_materials = DecryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, verification_key=b"ex_verification_key" - ) - - # Call on_decrypt function for the keyring - decryption_materials = fake_raw_aes_keyring.on_decrypt( - decryption_materials=decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys - ) - - # if decryption_materials.data_encryption_key: - # # Check if the data keys match - assert encryption_materials.data_encryption_key == decryption_materials.data_encryption_key From 7c021da1a1d365608172940afab71c13eda42f49 Mon Sep 17 00:00:00 2001 From: MeghaShetty Date: Tue, 23 Jul 2019 14:39:50 -0700 Subject: [PATCH 099/110] Delete test_f_keyring_raw_rsa.py --- test/functional/test_f_keyring_raw_rsa.py | 165 ---------------------- 1 file changed, 165 deletions(-) delete mode 100644 test/functional/test_f_keyring_raw_rsa.py diff --git a/test/functional/test_f_keyring_raw_rsa.py b/test/functional/test_f_keyring_raw_rsa.py deleted file mode 100644 index 0ce72b23c..000000000 --- a/test/functional/test_f_keyring_raw_rsa.py +++ /dev/null @@ -1,165 +0,0 @@ -# Copyright 2019 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. -"""Functional tests for Raw AES keyring encryption decryption path.""" - -import pytest -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives.asymmetric import rsa - -from aws_encryption_sdk.identifiers import Algorithm, KeyringTraceFlag, WrappingAlgorithm -from aws_encryption_sdk.keyring.raw_keyring import RawRSAKeyring -from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials -from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey - -pytestmark = [pytest.mark.functional, pytest.mark.local] - -_ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"} -_PROVIDER_ID = "Random Raw Keys" -_KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" -_SIGNING_KEY = b"aws-crypto-public-key" -_WRAPPING_ALGORITHM = WrappingAlgorithm.RSA_OAEP_SHA256_MGF1 -_PRIVATE_KEY = b"-----BEGIN RSA PRIVATE KEY-----"\ - b"MIICXgIBAAKBgQCUjhI8YRPXV8Gfofbg/"\ - b"PLjWw2AzowQTPErLU2z3+xGqElMdzdiC4Ta43DFWZg34Eg0X8kQPAeoe8h3cRSMo"\ - b"77eSOHt2dPo7OfTfZqsH8766fivHIKVxBYPX8SZYIUhMtRnlg3uqch9BksfRop+h"\ - b"f8h/H3lfervJoevS2CXYB9/iwIDAQABAoGBAIqeGzQOHbaGI51yQ2zjez1dPDdiB"\ - b"F49fZideHEM1GuGIodgguRQ/VJGgncUSC5zcMy2SGaGrVqwznltohAtxy4rZp0eh"\ - b"2O3aHYi9Wehd0SPLh+qwu7mJDuh0z15hmCOue070FnUtyuSwhXLwDrbot2+5HbmF"\ - b"9clJLI5tv92gvIpAkEA+Bv5i8XJNPN1rao31aQFoi9bFIOEclk3b1RbLX6mpZBFS"\ - b"U9CNUy0RQNC0+H3KZ5CTvsyFGpMfTdiFc/Qdesk3QJBAJlHjrvoadP+PU3zXYrWR"\ - b"D5EryyTxaP1bOjrp9xLuQBeU8x7EVJdpoul9OmwcT3NrAqvxDE9okjha2tjCI6O2"\ - b"4cCQQDMyOJPYL/zaaPO5LlTKB/SPv4RT4BplYPw6xKa2XeZHhxiJv5B2f7NG6T0G"\ - b"AWWn16hrCoouZhKngTidfXc7motAkA/KiTgvKr3yHp86AAxWZDv1CAYD6FPqrDB3"\ - b"3LiLnZDd5uy1ThTJ/Kc87vUnXhdDqeKE9qWrB53SCWbMElzbd17AkEA4DMp+6ngM"\ - b"o6sS0dY1X6nTLqgvK3B0z5GCAdSEy3Y8jh995Lrl+hy88HzuwUkQwwPlZkFhUNCx"\ - b"edrC6cTKE5xLA=="\ - b"-----END RSA PRIVATE KEY-----" - -_ENCRYPTION_MATERIALS = [ - EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - ), - EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - keyring_trace=[ - KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}, - ) - ], - ), - EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encrypted_data_keys=[ - EncryptedDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" - b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", - ) - ], - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - keyring_trace=[ - KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={ - KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, - KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY, - }, - ) - ], - ), -] - -_RAW_RSA_KEYRINGS = [ - RawRSAKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_key=rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend()), - wrapping_algorithm=_WRAPPING_ALGORITHM, - ), - RawRSAKeyring.fromPEMEncoding( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - encoded_key=_PRIVATE_KEY, - password=None, - wrapping_algorithm=_WRAPPING_ALGORITHM, - ), - # RawRSAKeyring.fromDEREncoding( - # key_namespace=_PROVIDER_ID, - # key_name=_KEY_ID, - # encoded_key=b"-----BEGIN RSA PRIVATE KEY-----\n" - # b"MIIEowIBAAKCAQEAo8uCyhiO4JUGZV+rtNq5DBA9Lm4xkw5kTA3v6EPybs8bVXL2\n" - # b"ZE6jkbo+xT4Jg/bKzUpnp1fE+T1ruGPtsPdoEmhY/P64LDNIs3sRq5U4QV9IETU1\n" - # b"vIcbNNkgGhRjV8J87YNY0tV0H7tuWuZRpqnS+gjV6V9lUMkbvjMCc5IBqQc3heut\n" - # b"/+fH4JwpGlGxOVXI8QAapnSy1XpCr3+PT29kydVJnIMuAoFrurojRpOQbOuVvhtA\n" - # b"gARhst1Ji4nfROGYkj6eZhvkz2Bkud4/+3lGvVU5LO1vD8oY7WoGtpin3h50VcWe\n" - # b"aBT4kejx4s9/G9C4R24lTH09J9HO2UUsuCqZYQIDAQABAoIBAQCfC90bCk+qaWqF\n" - # b"gymC+qOWwCn4bM28gswHQb1D5r6AtKBRD8mKywVvWs7azguFVV3Fi8sspkBA2FBC\n" - # b"At5p6ULoJOTL/TauzLl6djVJTCMM701WUDm2r+ZOIctXJ5bzP4n5Q4I7b0NMEL7u\n" - # b"ixib4elYGr5D1vrVQAKtZHCr8gmkqyx8Mz7wkJepzBP9EeVzETCHsmiQDd5WYlO1\n" - # b"C2IQYgw6MJzgM4entJ0V/GPytkodblGY95ORVK7ZhyNtda+r5BZ6/jeMW+hA3VoK\n" - # b"tHSWjHt06ueVCCieZIATmYzBNt+zEz5UA2l7ksg3eWfVORJQS7a6Ef4VvbJLM9Ca\n" - # b"m1kdsjelAoGBANKgvRf39i3bSuvm5VoyJuqinSb/23IH3Zo7XOZ5G164vh49E9Cq\n" - # b"dOXXVxox74ppj/kbGUoOk+AvaB48zzfzNvac0a7lRHExykPH2kVrI/NwH/1OcT/x\n" - # b"2e2DnFYocXcb4gbdZQ+m6X3zkxOYcONRzPVW1uMrFTWHcJveMUm4PGx7AoGBAMcU\n" - # b"IRvrT6ye5se0s27gHnPweV+3xjsNtXZcK82N7duXyHmNjxrwOAv0SOhUmTkRXArM\n" - # b"6aN5D8vyZBSWma2TgUKwpQYFTI+4Sp7sdkkyojGAEixJ+c5TZJNxZFrUe0FwAoic\n" - # b"c2kb7ntaiEj5G+qHvykJJro5hy6uLnjiMVbAiJDTAoGAKb67241EmHAXGEwp9sdr\n" - # b"2SMjnIAnQSF39UKAthkYqJxa6elXDQtLoeYdGE7/V+J2K3wIdhoPiuY6b4vD0iX9\n" - # b"JcGM+WntN7YTjX2FsC588JmvbWfnoDHR7HYiPR1E58N597xXdFOzgUgORVr4PMWQ\n" - # b"pqtwaZO3X2WZlvrhr+e46hMCgYBfdIdrm6jYXFjL6RkgUNZJQUTxYGzsY+ZemlNm\n" - # b"fGdQo7a8kePMRuKY2MkcnXPaqTg49YgRmjq4z8CtHokRcWjJUWnPOTs8rmEZUshk\n" - # b"0KJ0mbQdCFt/Uv0mtXgpFTkEZ3DPkDTGcV4oR4CRfOCl0/EU/A5VvL/U4i/mRo7h\n" - # b"ye+xgQKBgD58b+9z+PR5LAJm1tZHIwb4tnyczP28PzwknxFd2qylR4ZNgvAUqGtU\n" - # b"xvpUDpzMioz6zUH9YV43YNtt+5Xnzkqj+u9Mr27/H2v9XPwORGfwQ5XPwRJz/2oC\n" - # b"EnPmP1SZoY9lXKUpQXHXSpDZ2rE2Klt3RHMUMHt8Zpy36E8Vwx8o\n" - # b"-----END RSA PRIVATE KEY-----\n", - # password=None, - # wrapping_algorithm=_WRAPPING_ALGORITHM, - # ) -] - - -@pytest.mark.parametrize("encryption_materials_samples", _ENCRYPTION_MATERIALS) -@pytest.mark.parametrize("fake_raw_rsa_keyring", _RAW_RSA_KEYRINGS) -def test_raw_rsa_encryption_decryption(encryption_materials_samples, fake_raw_rsa_keyring): - - # Call on_encrypt function for the keyring - encryption_materials = fake_raw_rsa_keyring.on_encrypt(encryption_materials=encryption_materials_samples) - - # Generate decryption materials - decryption_materials = DecryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, verification_key=b"ex_verification_key" - ) - - # Call on_decrypt function for the keyring - decryption_materials = fake_raw_rsa_keyring.on_decrypt( - decryption_materials=decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys - ) - - # if decryption_materials.data_encryption_key: - # # Check if the data keys match - assert encryption_materials.data_encryption_key == decryption_materials.data_encryption_key From 115f804a5e2cb4c51d21dfaeecdf77a53f780e96 Mon Sep 17 00:00:00 2001 From: MeghaShetty Date: Tue, 23 Jul 2019 14:40:05 -0700 Subject: [PATCH 100/110] Delete test_keyring_raw_aes.py --- test/unit/test_keyring_raw_aes.py | 243 ------------------------------ 1 file changed, 243 deletions(-) delete mode 100644 test/unit/test_keyring_raw_aes.py diff --git a/test/unit/test_keyring_raw_aes.py b/test/unit/test_keyring_raw_aes.py deleted file mode 100644 index 85b483b10..000000000 --- a/test/unit/test_keyring_raw_aes.py +++ /dev/null @@ -1,243 +0,0 @@ -# Copyright 2019 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. -"""Unit tests for Raw AES keyring.""" - -import pytest -import six -from mock import MagicMock, patch, sentinel - -from aws_encryption_sdk.exceptions import GenerateKeyError -from aws_encryption_sdk.identifiers import Algorithm, KeyringTraceFlag, WrappingAlgorithm -from aws_encryption_sdk.keyring.base import EncryptedDataKey, Keyring -from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring, generate_data_key -from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials -from aws_encryption_sdk.structures import KeyringTrace, MasterKeyInfo, RawDataKey - -from .test_values import VALUES -# from .test_utils import NullRawAESKeyring - -try: # Python 3.5.0 and 3.5.1 have incompatible typing modules - from typing import Iterable # noqa pylint: disable=unused-import -except ImportError: # pragma: no cover - # We only actually need these imports when running the mypy checks - pass - -pytestmark = [pytest.mark.unit, pytest.mark.local] - -_ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"} -_PROVIDER_ID = "Random Raw Keys" -_KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" -_WRAPPING_KEY = b"\xeby-\x80A6\x15rA8\x83#,\xe4\xab\xac`\xaf\x99Z\xc1\xce\xdb\xb6\x0f\xb7\x805\xb2\x14J3" -_SIGNING_KEY = b"aws-crypto-public-key" -_DATA_KEY = ( - b"\x00\xfa\x8c\xdd\x08Au\xc6\x92_4\xc5\xfb\x90\xaf\x8f\xa1D\xaf\xcc\xd25" b"\xa8\x0b\x0b\x16\x92\x91W\x01\xb7\x84" -) -_ENCRYPTION_MATERIALS_WITH_DATA_KEY = EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - keyring_trace=[ - KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}, - ) - ], -) - -_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY = EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, -) - -_ENCRYPTION_MATERIALS_WITH_ENCRYPTED_DATA_KEY = EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encrypted_data_keys=[ - EncryptedDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" - b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", - ) - ], - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - keyring_trace=[ - KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}, - ) - ], -) - -_DECRYPTION_MATERIALS_WITH_DATA_KEY = DecryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encryption_context=_ENCRYPTION_CONTEXT, - verification_key=b"ex_verification_key", - keyring_trace=[KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} - )] -) - -_DECRYPTION_MATERIALS_WITHOUT_DATA_KEY = DecryptionMaterials( - verification_key=b"ex_verification_key", -) - - -class TestRawAESKeyring(object): - @pytest.fixture(autouse=True) - def apply_fixtures(self): - self.mock_encrypted_data_key = EncryptedDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - encrypted_data_key=VALUES["encrypted_data_key"], - ) - self.mock_encryption_materials = MagicMock() - self.mock_encryption_materials.__class__ = EncryptionMaterials - - def test_parent(self): - assert issubclass(RawAESKeyring, Keyring) - - # def test_initialization(self): - # test = RawAESKeyring( - # key_namespace=_PROVIDER_ID, - # key_name=_KEY_ID, - # wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, - # wrapping_key=_WRAPPING_KEY, - # ) - # assert test.__getattribute__(key_provider) == self.mock_encrypted_data_key.key_provider - - @patch("aws_encryption_sdk.keyring.raw_keyring.generate_data_key") - def test_data_encryption_key_provided(self, mock_generate_data_key): - mock_generate_data_key.return_value = _DATA_KEY - test_raw_aes_keyring = RawAESKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, - wrapping_key=_WRAPPING_KEY, - ) - - test = test_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITH_DATA_KEY) - # Check if keyring is generated - assert not mock_generate_data_key.called - - # Check if data encryption key is encrypted - assert test.encrypted_data_keys is not None - - def test_data_encryption_key_generated(self): - test_raw_aes_keyring = RawAESKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, - wrapping_key=_WRAPPING_KEY, - ) - test = test_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY) - - # Check if key is generated - if not test.data_encryption_key: - # Check if error thrown if data key is not generated - assert pytest.raises(GenerateKeyError, "Unable to generate data encryption key.") - else: - # Check if data key is generated - assert test.data_encryption_key and test.data_encryption_key is not None - assert test.encrypted_data_keys and test.encrypted_data_keys is not None - - @patch("aws_encryption_sdk.keyring.raw_keyring.generate_data_key") - def test_encrypted_data_key_provided(self, mock_generate_data_key): - mock_generate_data_key.return_value = _DATA_KEY - test_raw_aes_keyring = RawAESKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, - wrapping_key=_WRAPPING_KEY, - ) - test = test_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITH_ENCRYPTED_DATA_KEY) - - # Check if generate_data_key is called - assert not mock_generate_data_key.called - # - # Check if encrypt is called - assert len(test.encrypted_data_keys) == len(_ENCRYPTION_MATERIALS_WITH_ENCRYPTED_DATA_KEY.encrypted_data_keys) - - # @patch("aws_encryption_sdk.key_providers.raw.os.urandom") - # def test_data_key_not_generated(self, mock_os_urandom): - # mock_os_urandom.return_value = None - # test_raw_aes_keyring = RawAESKeyring( - # key_namespace=_PROVIDER_ID, - # key_name=_KEY_ID, - # wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, - # wrapping_key=_WRAPPING_KEY, - # ) - # test = test_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY) - # assert pytest.raises(GenerateKeyError, "Unable to generate data encryption key.") - - @patch("aws_encryption_sdk.keyring.raw_keyring.generate_data_key") - def test_data_key_not_generated(self, mock_generate_data_key): - mock_generate_data_key.return_value = None - test_raw_aes_keyring = RawAESKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, - wrapping_key=_WRAPPING_KEY, - ) - test = test_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY) - assert pytest.raises(GenerateKeyError) - - @patch("aws_encryption_sdk.internal.crypto.wrapping_keys.WrappingKey.decrypt") - def test_decrypt_when_data_key_provided(self, mock_decrypt): - mock_decrypt.return_value = _DATA_KEY - test_raw_aes_keyring = RawAESKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, - wrapping_key=_WRAPPING_KEY, - ) - test = test_raw_aes_keyring.on_decrypt(decryption_materials=_DECRYPTION_MATERIALS_WITH_DATA_KEY, - encrypted_data_keys=[self.mock_encrypted_data_key]) - assert not mock_decrypt.called - - # @patch("aws_encryption_sdk.internal.crypto.wrapping_keys.WrappingKey.decrypt") - # def test_decrypt_when_data_key_not_provided(self, mock_decrypt): - # mock_decrypt.return_value = _DATA_KEY - # test_raw_aes_keyring = RawAESKeyring( - # key_namespace=_PROVIDER_ID, - # key_name=_KEY_ID, - # wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, - # wrapping_key=_WRAPPING_KEY, - # ) - # - # test = test_raw_aes_keyring.on_decrypt(decryption_materials=_DECRYPTION_MATERIALS_WITHOUT_DATA_KEY, - # encrypted_data_keys=[ - # EncryptedDataKey( - # key_provider=MasterKeyInfo( - # provider_id=_PROVIDER_ID, - # key_info=_KEY_ID), - # encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\ - # xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" - # b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\ - # x07FzE\xde", - # ) - # ] - # ) - # assert mock_decrypt.called From 3f9a3c06c07d75ac852468b3aee0b9928fd1d549 Mon Sep 17 00:00:00 2001 From: MeghaShetty Date: Tue, 23 Jul 2019 14:40:13 -0700 Subject: [PATCH 101/110] Delete test_keyring_raw_rsa.py --- test/unit/test_keyring_raw_rsa.py | 244 ------------------------------ 1 file changed, 244 deletions(-) delete mode 100644 test/unit/test_keyring_raw_rsa.py diff --git a/test/unit/test_keyring_raw_rsa.py b/test/unit/test_keyring_raw_rsa.py deleted file mode 100644 index 532cfc01e..000000000 --- a/test/unit/test_keyring_raw_rsa.py +++ /dev/null @@ -1,244 +0,0 @@ -# Copyright 2019 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. -"""Unit tests for Raw AES keyring.""" - -import pytest -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives.asymmetric import rsa -from mock import MagicMock, patch, sentinel - -from aws_encryption_sdk.exceptions import GenerateKeyError -from aws_encryption_sdk.identifiers import Algorithm, KeyringTraceFlag, WrappingAlgorithm -from aws_encryption_sdk.keyring.base import EncryptedDataKey, Keyring -from aws_encryption_sdk.keyring.raw_keyring import RawRSAKeyring, generate_data_key -from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials -from aws_encryption_sdk.structures import KeyringTrace, MasterKeyInfo, RawDataKey - -from .test_values import VALUES -# from .test_utils import NullRawAESKeyring - -try: # Python 3.5.0 and 3.5.1 have incompatible typing modules - from typing import Iterable # noqa pylint: disable=unused-import -except ImportError: # pragma: no cover - # We only actually need these imports when running the mypy checks - pass - -pytestmark = [pytest.mark.unit, pytest.mark.local] - -_ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"} -_PROVIDER_ID = "Random Raw Keys" -_KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" -_WRAPPING_KEY = rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend()) -_SIGNING_KEY = b"aws-crypto-public-key" -_DATA_KEY = ( - b"\x00\xfa\x8c\xdd\x08Au\xc6\x92_4\xc5\xfb\x90\xaf\x8f\xa1D\xaf\xcc\xd25" b"\xa8\x0b\x0b\x16\x92\x91W\x01\xb7\x84" -) -_ENCRYPTION_MATERIALS_WITH_DATA_KEY = EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - keyring_trace=[ - KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}, - ) - ], -) - -_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY = EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, -) - -_ENCRYPTION_MATERIALS_WITH_ENCRYPTED_DATA_KEY = EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encrypted_data_keys=[ - EncryptedDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" - b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", - ) - ], - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - keyring_trace=[ - KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}, - ) - ], -) - -_DECRYPTION_MATERIALS_WITH_DATA_KEY = DecryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encryption_context=_ENCRYPTION_CONTEXT, - verification_key=b"ex_verification_key", - keyring_trace=[KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} - )] -) - -_DECRYPTION_MATERIALS_WITHOUT_DATA_KEY = DecryptionMaterials( - verification_key=b"ex_verification_key", -) - - -class TestRawRSAKeyring(object): - @pytest.fixture(autouse=True) - def apply_fixtures(self): - self.mock_encrypted_data_key = EncryptedDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - encrypted_data_key=VALUES["encrypted_data_key"], - ) - self.mock_encryption_materials = MagicMock() - self.mock_encryption_materials.__class__ = EncryptionMaterials - - def test_parent(self): - assert issubclass(RawRSAKeyring, Keyring) - - # def test_initialization(self): - # test = RawAESKeyring( - # key_namespace=_PROVIDER_ID, - # key_name=_KEY_ID, - # wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, - # wrapping_key=_WRAPPING_KEY, - # ) - # assert test.__getattribute__(key_provider) == self.mock_encrypted_data_key.key_provider - - @patch("aws_encryption_sdk.keyring.raw_keyring.generate_data_key") - def test_data_encryption_key_provided(self, mock_generate_data_key): - mock_generate_data_key.return_value = _DATA_KEY - test_raw_rsa_keyring = RawRSAKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, - wrapping_key=_WRAPPING_KEY, - ) - - test = test_raw_rsa_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITH_DATA_KEY) - # Check if keyring is generated - assert not mock_generate_data_key.called - - # Check if data encryption key is encrypted - assert test.encrypted_data_keys is not None - - def test_data_encryption_key_generated(self): - test_raw_rsa_keyring = RawRSAKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, - wrapping_key=_WRAPPING_KEY, - ) - test = test_raw_rsa_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY) - - # Check if key is generated - if not test.data_encryption_key: - # Check if error thrown if data key is not generated - assert pytest.raises(GenerateKeyError, "Unable to generate data encryption key.") - else: - # Check if data key is generated - assert test.data_encryption_key and test.data_encryption_key is not None - assert test.encrypted_data_keys and test.encrypted_data_keys is not None - - @patch("aws_encryption_sdk.keyring.raw_keyring.generate_data_key") - def test_encrypted_data_key_provided(self, mock_generate_data_key): - mock_generate_data_key.return_value = _DATA_KEY - test_raw_rsa_keyring = RawRSAKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, - wrapping_key=_WRAPPING_KEY, - ) - test = test_raw_rsa_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITH_ENCRYPTED_DATA_KEY) - - # Check if generate_data_key is called - assert not mock_generate_data_key.called - # - # Check if encrypt is called - assert len(test.encrypted_data_keys) == len(_ENCRYPTION_MATERIALS_WITH_ENCRYPTED_DATA_KEY.encrypted_data_keys) - - # @patch("aws_encryption_sdk.key_providers.raw.os.urandom") - # def test_data_key_not_generated(self, mock_os_urandom): - # mock_os_urandom.return_value = None - # test_raw_aes_keyring = RawAESKeyring( - # key_namespace=_PROVIDER_ID, - # key_name=_KEY_ID, - # wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, - # wrapping_key=_WRAPPING_KEY, - # ) - # test = test_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY) - # assert pytest.raises(GenerateKeyError, "Unable to generate data encryption key.") - - @patch("aws_encryption_sdk.keyring.raw_keyring.generate_data_key") - def test_data_key_not_generated(self, mock_generate_data_key): - mock_generate_data_key.return_value = None - test_raw_rsa_keyring = RawRSAKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, - wrapping_key=_WRAPPING_KEY, - ) - test = test_raw_rsa_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY) - assert pytest.raises(GenerateKeyError) - - @patch("aws_encryption_sdk.internal.crypto.wrapping_keys.WrappingKey.decrypt") - def test_decrypt_when_data_key_provided(self, mock_decrypt): - mock_decrypt.return_value = _DATA_KEY - test_raw_rsa_keyring = RawRSAKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, - wrapping_key=_WRAPPING_KEY, - ) - test = test_raw_rsa_keyring.on_decrypt(decryption_materials=_DECRYPTION_MATERIALS_WITH_DATA_KEY, - encrypted_data_keys=[self.mock_encrypted_data_key]) - assert not mock_decrypt.called - - # @patch("aws_encryption_sdk.internal.crypto.wrapping_keys.WrappingKey.decrypt") - # def test_decrypt_when_data_key_not_provided(self, mock_decrypt): - # mock_decrypt.return_value = _DATA_KEY - # test_raw_aes_keyring = RawAESKeyring( - # key_namespace=_PROVIDER_ID, - # key_name=_KEY_ID, - # wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, - # wrapping_key=_WRAPPING_KEY, - # ) - # - # test = test_raw_aes_keyring.on_decrypt(decryption_materials=_DECRYPTION_MATERIALS_WITHOUT_DATA_KEY, - # encrypted_data_keys=[ - # EncryptedDataKey( - # key_provider=MasterKeyInfo( - # provider_id=_PROVIDER_ID, - # key_info=_KEY_ID), - # encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\ - # xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" - # b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\ - # x07FzE\xde", - # ) - # ] - # ) - # assert mock_decrypt.called From d2bb7740dda4276c33e1c9c1a2790b8d3ba1b9fd Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 23 Jul 2019 15:54:46 -0700 Subject: [PATCH 102/110] Suggested changes --- test/unit/test_keyring_base.py | 17 ++++++++++------- test/unit/test_utils.py | 10 +--------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/test/unit/test_keyring_base.py b/test/unit/test_keyring_base.py index 6f40dc794..92241fd6a 100644 --- a/test/unit/test_keyring_base.py +++ b/test/unit/test_keyring_base.py @@ -57,17 +57,20 @@ ] -def test_keyring_no_encrypt(): - class KeyringNoEncrypt(Keyring): - def on_decrypt(self, _decryption_materials, _encrypted_data_keys): - return +class KeyringNoEncrypt(Keyring): + def on_decrypt(self, _decryption_materials, _encrypted_data_keys): + return _decryption_materials + + +class KeyringNoDecrypt(Keyring): + def on_encrypt(self, _encryption_materials): + return _encryption_materials + +def test_keyring_no_encrypt(): assert pytest.raises(NotImplementedError) def test_keyring_no_decrypt(): - class KeyringNoDecrypt(Keyring): - def on_encrypt(self, _encryption_materials): - return assert pytest.raises(NotImplementedError) diff --git a/test/unit/test_utils.py b/test/unit/test_utils.py index 0da12a869..0cb244fb2 100644 --- a/test/unit/test_utils.py +++ b/test/unit/test_utils.py @@ -29,7 +29,7 @@ from .unit_test_utils import assert_prepped_stream_identity try: # Python 3.5.0 and 3.5.1 have incompatible typing modules - from typing import Iterable, Union # noqa pylint: disable=unused-import + from typing import Iterable # noqa pylint: disable=unused-import except ImportError: # pragma: no cover # We only actually need these imports when running the mypy checks pass @@ -60,14 +60,6 @@ def on_decrypt(self, decryption_materials, encrypted_data_keys): return decryption_materials -class NullRawAESKeyring(RawAESKeyring): - def on_encrypt(self): - return - - def on_decrypt(self): - return - - class TestUtils(object): @pytest.fixture(autouse=True) def apply_fixtures(self): From 3620b58f6eff8668c70083c69654cddbdff6fc00 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 23 Jul 2019 17:18:18 -0700 Subject: [PATCH 103/110] Made suggested changes to base API and tests --- examples/src/sample_aes.py | 78 ---- src/aws_encryption_sdk/keyring/raw_keyring.py | 394 ------------------ test/functional/test_f_keyring_raw_aes.py | 113 ----- test/functional/test_f_keyring_raw_rsa.py | 165 -------- test/unit/test_keyring_base.py | 28 +- test/unit/test_keyring_raw_aes.py | 243 ----------- test/unit/test_keyring_raw_rsa.py | 244 ----------- test/unit/test_utils.py | 12 - 8 files changed, 8 insertions(+), 1269 deletions(-) delete mode 100644 examples/src/sample_aes.py delete mode 100644 src/aws_encryption_sdk/keyring/raw_keyring.py delete mode 100644 test/functional/test_f_keyring_raw_aes.py delete mode 100644 test/functional/test_f_keyring_raw_rsa.py delete mode 100644 test/unit/test_keyring_raw_aes.py delete mode 100644 test/unit/test_keyring_raw_rsa.py diff --git a/examples/src/sample_aes.py b/examples/src/sample_aes.py deleted file mode 100644 index d9d37f37a..000000000 --- a/examples/src/sample_aes.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright 2019 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. -"""Functional tests for Raw AES keyring encryption decryption path.""" - -import pytest - -from aws_encryption_sdk.identifiers import Algorithm, WrappingAlgorithm -from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring -from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials - -pytestmark = [pytest.mark.functional, pytest.mark.local] - -_ENCRYPTION_CONTEXT = {"key_a": "value_a", "key_b": "value_b", "key_c": "value_c"} -_PROVIDER_ID = "Random Raw Keys" -_KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" -_WRAPPING_KEY = b"12345678901234567890123456789012" -_SIGNING_KEY = b"aws-crypto-public-key" - -_ENCRYPTION_MATERIALS = EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - ) - - -def sample_aes_encryption_decryption(): - - # Initializing attributes - key_namespace = _PROVIDER_ID - key_name = _KEY_ID - _wrapping_algorithm = WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING - - # Creating an instance of a raw AES keyring - fake_raw_aes_keyring = RawAESKeyring( - key_namespace=key_namespace, - key_name=key_name, - wrapping_key=_WRAPPING_KEY, - wrapping_algorithm=_wrapping_algorithm, - ) - - # Call on_encrypt function for the keyring - encryption_materials = fake_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS) - - print("PLAINTEXT DATA KEY") - print(encryption_materials.data_encryption_key.data_key) - - print("ENCRYPTED DATA KEY") - print(encryption_materials.encrypted_data_keys) - - # Generate decryption materials - decryption_materials = DecryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, verification_key=b"ex_verification_key" - ) - - # Call on_decrypt function for the keyring - decryption_materials = fake_raw_aes_keyring.on_decrypt( - decryption_materials=decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys - ) - - print("DECRYPTED DATA KEY") - print(decryption_materials.data_encryption_key.data_key) - - if decryption_materials.data_encryption_key: - # Check if the data keys match - assert encryption_materials.data_encryption_key == decryption_materials.data_encryption_key - - -sample_aes_encryption_decryption() diff --git a/src/aws_encryption_sdk/keyring/raw_keyring.py b/src/aws_encryption_sdk/keyring/raw_keyring.py deleted file mode 100644 index 3cfdf9c21..000000000 --- a/src/aws_encryption_sdk/keyring/raw_keyring.py +++ /dev/null @@ -1,394 +0,0 @@ -# Copyright 2017 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. -"""Resources required for Raw Keyrings.""" - -import logging -import os - -import attr -import six -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives import serialization -from cryptography.hazmat.primitives.asymmetric import padding, rsa - -from aws_encryption_sdk.exceptions import GenerateKeyError -from aws_encryption_sdk.identifiers import EncryptionKeyType, KeyringTraceFlag, 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.keyring.base import Keyring -from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials -from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey - -try: # Python 3.5.0 and 3.5.1 have incompatible typing modules - from typing import Iterable, Union # noqa pylint: disable=unused-import -except ImportError: # pragma: no cover - # We only actually need these imports when running the mypy checks - pass - - -def get_key_info_prefix(key_namespace, key_name, wrapping_key): - # type: (str, bytes, WrappingKey) -> six.binary_type - """Helper function to get key info prefix - - :param str key_namespace: String defining the keyring. - :param bytes key_name: Key ID - :param wrapping_key: Encryption key with which to wrap plaintext data key. - :type wrapping_key: WrappingKey - :return: Serialized key_info prefix - :rtype: bytes - """ - key_info_prefix = serialize_raw_master_key_prefix( - RawMasterKey(provider_id=key_namespace, key_id=key_name, wrapping_key=wrapping_key) - ) - return key_info_prefix - - -def generate_data_key( - encryption_materials, # type: EncryptionMaterials - key_provider, # type: MasterKeyInfo -): - # type: (...) -> bytes - """Generates plaintext data key for the keyring. - - :param encryption_materials: Encryption materials for the keyring to modify. - :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials - :param key_provider: Information about the key in the keyring. - :type key_provider: MasterKeyInfo - :return bytes: Plaintext data key - """ - # Generate data key - plaintext_data_key = os.urandom(encryption_materials.algorithm.kdf_input_len) - - # Check if data key is generated - if not plaintext_data_key or plaintext_data_key is None: - raise GenerateKeyError("Unable to generate data encryption key.") - - # Create a keyring trace - keyring_trace = KeyringTrace(wrapping_key=key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}) - - # plaintext_data_key to RawDataKey - data_encryption_key = RawDataKey(key_provider=key_provider, data_key=plaintext_data_key) - - # Add generated data key to encryption_materials - encryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) - - return plaintext_data_key - - -@attr.s -class RawAESKeyring(Keyring): - """Public class for Raw AES Keyring. - - :param str key_namespace: String defining the keyring. - :param bytes key_name: Key ID - :param bytes wrapping_key: Encryption key with which to wrap plaintext data key. - :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key. - :type wrapping_algorithm: WrappingAlgorithm - """ - - key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) - key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) - _wrapping_key = attr.ib(repr=False, validator=attr.validators.instance_of(six.binary_type)) - _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) - - def __attrs_post_init__(self): - # type: () -> None - """Prepares initial values not handled by attrs.""" - self._key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name) - - self._wrapping_key_structure = WrappingKey( - wrapping_algorithm=self._wrapping_algorithm, - wrapping_key=self._wrapping_key, - wrapping_key_type=EncryptionKeyType.SYMMETRIC, - ) - - self._key_info_prefix = get_key_info_prefix( - key_namespace=self.key_namespace, key_name=self.key_name, wrapping_key=self._wrapping_key_structure - ) - - def on_encrypt(self, encryption_materials): - # type: (EncryptionMaterials) -> EncryptionMaterials - """Generate a data key if not present and encrypt it using any available wrapping key - - :param encryption_materials: Encryption materials for the keyring to modify - :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials - :returns: Optionally modified encryption materials - :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials - """ - if not encryption_materials.data_encryption_key: - plaintext_data_key = generate_data_key( - encryption_materials=encryption_materials, key_provider=self._key_provider - ) - else: - plaintext_data_key = encryption_materials.data_encryption_key.data_key - - # Check if data key exists - if not plaintext_data_key or plaintext_data_key is None: - raise GenerateKeyError("Unable to generate data encryption key.") - - # Encrypt data key - encrypted_wrapped_key = self._wrapping_key_structure.encrypt( - plaintext_data_key=plaintext_data_key, encryption_context=encryption_materials.encryption_context - ) - - # EncryptedData to EncryptedDataKey - encrypted_data_key = serialize_wrapped_key( - key_provider=self._key_provider, - wrapping_algorithm=self._wrapping_algorithm, - wrapping_key_id=self.key_name, - encrypted_wrapped_key=encrypted_wrapped_key, - ) - - # Update Keyring Trace - if encrypted_data_key: - keyring_trace = KeyringTrace( - wrapping_key=encrypted_data_key.key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY} - ) - - # Add encrypted data key to encryption_materials - encryption_materials.add_encrypted_data_key( - encrypted_data_key=encrypted_data_key, keyring_trace=keyring_trace - ) - return encryption_materials - - def on_decrypt(self, decryption_materials, encrypted_data_keys): - # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials - """Attempt to decrypt the encrypted data keys. - - :param decryption_materials: Decryption materials for the keyring to modify - :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials - :param encrypted_data_keys: List of encrypted data keys - :type: List of `aws_encryption_sdk.structures.EncryptedDataKey` - :returns: Optionally modified decryption materials - :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials - """ - if decryption_materials.data_encryption_key: - return decryption_materials - - # Decrypt data key - expected_key_info_len = len(self._key_info_prefix) + self._wrapping_algorithm.algorithm.iv_len - for key in encrypted_data_keys: - if ( - key.key_provider.provider_id == self._key_provider.provider_id - and len(key.key_provider.key_info) == expected_key_info_len - and key.key_provider.key_info.startswith(self._key_info_prefix) - ): - # Wrapped EncryptedDataKey to deserialized EncryptedData - encrypted_wrapped_key = deserialize_wrapped_key( - wrapping_algorithm=self._wrapping_algorithm, - wrapping_key_id=self.key_name, - wrapped_encrypted_key=key, - ) - # EncryptedData to raw key string - try: - plaintext_data_key = self._wrapping_key_structure.decrypt( - encrypted_wrapped_data_key=encrypted_wrapped_key, - encryption_context=decryption_materials.encryption_context, - ) - - except Exception as error: # pylint: disable=broad-except - logger = logging.getLogger(__name__) - logger.error(error.__class__.__name__, ":", str(error)) - return decryption_materials - - if plaintext_data_key: - # Create a keyring trace - keyring_trace = KeyringTrace( - wrapping_key=self._key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} - ) - - # Update decryption materials - data_encryption_key = RawDataKey( - key_provider=MasterKeyInfo(provider_id=self._key_provider.provider_id, key_info=self.key_name), - data_key=plaintext_data_key, - ) - decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) - - if decryption_materials.data_encryption_key: - return decryption_materials - - return decryption_materials - - -@attr.s -class RawRSAKeyring(Keyring): - """Public class for Raw RSA Keyring. - - :param str key_namespace: String defining the keyring ID - :param bytes key_name: Key ID - :param wrapping_key: Encryption key with which to wrap plaintext data key - :type wrapping_key: object - :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext data key - :type wrapping_algorithm: WrappingAlgorithm - :param key_provider: Complete information about the key in the keyring - :type key_provider: MasterKeyInfo - """ - - key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) - key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) - # _wrapping_key = attr.ib(repr=False, validator=attr.validators.in_([rsa.RSAPrivateKey, rsa.RSAPublicKey])) - # ----- need to figure out how to do this correctly - _wrapping_key = attr.ib(repr=False, validator=attr.validators.instance_of(object)) - _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) - - @classmethod - def fromPEMEncoding(cls, key_namespace, key_name, encoded_key, password, wrapping_algorithm): - # key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) - # key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) - # _encoded_key = attr.ib(validator=attr.validators.instance_of(six.binary_type)) - # _password = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(six.binary_type))) - # _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) - if password: - loaded_wrapping_key = serialization.load_pem_private_key( - data=encoded_key, password=password, backend=default_backend() - ) - else: - loaded_wrapping_key = serialization.load_pem_public_key(data=encoded_key, backend=default_backend()) - return cls( - key_namespace=key_namespace, - key_name=key_name, - wrapping_key=loaded_wrapping_key, - wrapping_algorithm=wrapping_algorithm, - ) - - @classmethod - def fromDEREncoding(cls, key_namespace, key_name, encoded_key, password, wrapping_algorithm): - # key_namespace = attr.ib(validator=attr.validators.instance_of(six.string_types)) - # key_name = attr.ib(validator=attr.validators.instance_of(six.binary_type)) - # _encoded_key = attr.ib(validator=attr.validators.instance_of(six.binary_type)) - # _password = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(six.binary_type))) - # _wrapping_algorithm = attr.ib(repr=False, validator=attr.validators.instance_of(WrappingAlgorithm)) - if password: - loaded_wrapping_key = serialization.load_der_private_key( - data=encoded_key, password=password, backend=default_backend() - ) - else: - loaded_wrapping_key = serialization.load_der_public_key(data=encoded_key, backend=default_backend()) - return cls( - key_namespace=key_namespace, - key_name=key_name, - wrapping_key=loaded_wrapping_key, - wrapping_algorithm=wrapping_algorithm, - ) - - def __attrs_post_init__(self): - # type: () -> None - """Prepares initial values not handled by attrs.""" - self._key_provider = MasterKeyInfo(provider_id=self.key_namespace, key_info=self.key_name) - - def on_encrypt(self, encryption_materials): - # type: (EncryptionMaterials) -> EncryptionMaterials - """Generate a data key if not present and encrypt it using any available wrapping key. - - :param encryption_materials: Encryption materials for the keyring to modify. - :type encryption_materials: aws_encryption_sdk.materials_managers.EncryptionMaterials - :returns: Optionally modified encryption materials. - :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials - """ - if not encryption_materials.data_encryption_key: - plaintext_data_key = generate_data_key( - encryption_materials=encryption_materials, key_provider=self._key_provider - ) - else: - plaintext_data_key = encryption_materials.data_encryption_key.data_key - if isinstance(self._wrapping_key, rsa.RSAPublicKey): - - # Encrypt data key - encrypted_wrapped_key = EncryptedData( - iv=None, - ciphertext=self._wrapping_key.encrypt( - plaintext=plaintext_data_key, padding=self._wrapping_algorithm.padding - ), - tag=None, - ) - else: - # Encrypt data key - encrypted_wrapped_key = EncryptedData( - iv=None, - ciphertext=self._wrapping_key.public_key().encrypt( - plaintext=plaintext_data_key, padding=self._wrapping_algorithm.padding - ), - tag=None, - ) - - # EncryptedData to EncryptedDataKey - encrypted_data_key = serialize_wrapped_key( - key_provider=self._key_provider, - wrapping_algorithm=self._wrapping_algorithm, - wrapping_key_id=self.key_name, - encrypted_wrapped_key=encrypted_wrapped_key, - ) - - # Update Keyring Trace - if encrypted_data_key: - keyring_trace = KeyringTrace( - wrapping_key=encrypted_data_key.key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY} - ) - - # Add encrypted data key to encryption_materials - encryption_materials.add_encrypted_data_key( - encrypted_data_key=encrypted_data_key, keyring_trace=keyring_trace - ) - - return encryption_materials - - def on_decrypt(self, decryption_materials, encrypted_data_keys): - # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials - """Attempt to decrypt the encrypted data keys. - - :param decryption_materials: Decryption materials for the keyring to modify. - :type decryption_materials: aws_encryption_sdk.materials_managers.DecryptionMaterials - :param encrypted_data_keys: List of encrypted data keys. - :type: List of `aws_encryption_sdk.structures.EncryptedDataKey` - :returns: Optionally modified decryption materials. - :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials - """ - if isinstance(self._wrapping_key, rsa.RSAPrivateKey): - # Decrypt data key - for key in encrypted_data_keys: - if key.key_provider == self._key_provider: - # Wrapped EncryptedDataKey to deserialized EncryptedData - encrypted_wrapped_key = deserialize_wrapped_key( - wrapping_algorithm=self._wrapping_algorithm, - wrapping_key_id=self.key_name, - wrapped_encrypted_key=key, - ) - try: - plaintext_data_key = self._wrapping_key.decrypt( - ciphertext=encrypted_wrapped_key.ciphertext, padding=self._wrapping_algorithm.padding - ) - except Exception as error: # pylint: disable=broad-except - logger = logging.getLogger() - logger.error(error.__class__.__name__, ":", str(error)) - return decryption_materials - - if plaintext_data_key: - # Create a keyring trace - keyring_trace = KeyringTrace( - wrapping_key=self._key_provider, flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} - ) - - # Update decryption materials - data_encryption_key = RawDataKey( - key_provider=MasterKeyInfo( - provider_id=self._key_provider.provider_id, key_info=self.key_name - ), - data_key=plaintext_data_key, - ) - decryption_materials.add_data_encryption_key(data_encryption_key, keyring_trace) - if decryption_materials.data_encryption_key: - return decryption_materials - - return decryption_materials diff --git a/test/functional/test_f_keyring_raw_aes.py b/test/functional/test_f_keyring_raw_aes.py deleted file mode 100644 index 18c0638bc..000000000 --- a/test/functional/test_f_keyring_raw_aes.py +++ /dev/null @@ -1,113 +0,0 @@ -# Copyright 2019 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. -"""Functional tests for Raw AES keyring encryption decryption path.""" - -import pytest - -from aws_encryption_sdk.identifiers import Algorithm, KeyringTraceFlag, WrappingAlgorithm -from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring -from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials -from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey - -pytestmark = [pytest.mark.functional, pytest.mark.local] - -_ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"} -_PROVIDER_ID = "Random Raw Keys" -_KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" -_WRAPPING_KEY = b"12345678901234567890123456789012" -_SIGNING_KEY = b"aws-crypto-public-key" - -_ENCRYPTION_MATERIALS = [ - EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - ), - EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - keyring_trace=[ - KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}, - ) - ], - ), - EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encrypted_data_keys=[ - EncryptedDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" - b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", - ) - ], - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - keyring_trace=[ - KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={ - KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, - KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY, - }, - ) - ], - ), -] - - -@pytest.mark.parametrize("encryption_materials_samples", _ENCRYPTION_MATERIALS) -def test_raw_aes_encryption_decryption(encryption_materials_samples): - - # Initializing attributes - key_namespace = _PROVIDER_ID - key_name = _KEY_ID - _wrapping_algorithm = WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING - - # Creating an instance of a raw AES keyring - fake_raw_aes_keyring = RawAESKeyring( - key_namespace=key_namespace, - key_name=key_name, - wrapping_key=_WRAPPING_KEY, - wrapping_algorithm=_wrapping_algorithm, - ) - - # Call on_encrypt function for the keyring - encryption_materials = fake_raw_aes_keyring.on_encrypt(encryption_materials=encryption_materials_samples) - - print("PLAINTEXT DATA KEY") - print(encryption_materials.data_encryption_key) - - # Generate decryption materials - decryption_materials = DecryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, verification_key=b"ex_verification_key" - ) - - # Call on_decrypt function for the keyring - decryption_materials = fake_raw_aes_keyring.on_decrypt( - decryption_materials=decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys - ) - - # if decryption_materials.data_encryption_key: - # # Check if the data keys match - assert encryption_materials.data_encryption_key == decryption_materials.data_encryption_key diff --git a/test/functional/test_f_keyring_raw_rsa.py b/test/functional/test_f_keyring_raw_rsa.py deleted file mode 100644 index 0ce72b23c..000000000 --- a/test/functional/test_f_keyring_raw_rsa.py +++ /dev/null @@ -1,165 +0,0 @@ -# Copyright 2019 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. -"""Functional tests for Raw AES keyring encryption decryption path.""" - -import pytest -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives.asymmetric import rsa - -from aws_encryption_sdk.identifiers import Algorithm, KeyringTraceFlag, WrappingAlgorithm -from aws_encryption_sdk.keyring.raw_keyring import RawRSAKeyring -from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials -from aws_encryption_sdk.structures import EncryptedDataKey, KeyringTrace, MasterKeyInfo, RawDataKey - -pytestmark = [pytest.mark.functional, pytest.mark.local] - -_ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"} -_PROVIDER_ID = "Random Raw Keys" -_KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" -_SIGNING_KEY = b"aws-crypto-public-key" -_WRAPPING_ALGORITHM = WrappingAlgorithm.RSA_OAEP_SHA256_MGF1 -_PRIVATE_KEY = b"-----BEGIN RSA PRIVATE KEY-----"\ - b"MIICXgIBAAKBgQCUjhI8YRPXV8Gfofbg/"\ - b"PLjWw2AzowQTPErLU2z3+xGqElMdzdiC4Ta43DFWZg34Eg0X8kQPAeoe8h3cRSMo"\ - b"77eSOHt2dPo7OfTfZqsH8766fivHIKVxBYPX8SZYIUhMtRnlg3uqch9BksfRop+h"\ - b"f8h/H3lfervJoevS2CXYB9/iwIDAQABAoGBAIqeGzQOHbaGI51yQ2zjez1dPDdiB"\ - b"F49fZideHEM1GuGIodgguRQ/VJGgncUSC5zcMy2SGaGrVqwznltohAtxy4rZp0eh"\ - b"2O3aHYi9Wehd0SPLh+qwu7mJDuh0z15hmCOue070FnUtyuSwhXLwDrbot2+5HbmF"\ - b"9clJLI5tv92gvIpAkEA+Bv5i8XJNPN1rao31aQFoi9bFIOEclk3b1RbLX6mpZBFS"\ - b"U9CNUy0RQNC0+H3KZ5CTvsyFGpMfTdiFc/Qdesk3QJBAJlHjrvoadP+PU3zXYrWR"\ - b"D5EryyTxaP1bOjrp9xLuQBeU8x7EVJdpoul9OmwcT3NrAqvxDE9okjha2tjCI6O2"\ - b"4cCQQDMyOJPYL/zaaPO5LlTKB/SPv4RT4BplYPw6xKa2XeZHhxiJv5B2f7NG6T0G"\ - b"AWWn16hrCoouZhKngTidfXc7motAkA/KiTgvKr3yHp86AAxWZDv1CAYD6FPqrDB3"\ - b"3LiLnZDd5uy1ThTJ/Kc87vUnXhdDqeKE9qWrB53SCWbMElzbd17AkEA4DMp+6ngM"\ - b"o6sS0dY1X6nTLqgvK3B0z5GCAdSEy3Y8jh995Lrl+hy88HzuwUkQwwPlZkFhUNCx"\ - b"edrC6cTKE5xLA=="\ - b"-----END RSA PRIVATE KEY-----" - -_ENCRYPTION_MATERIALS = [ - EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - ), - EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - keyring_trace=[ - KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}, - ) - ], - ), - EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encrypted_data_keys=[ - EncryptedDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" - b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", - ) - ], - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - keyring_trace=[ - KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={ - KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, - KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY, - }, - ) - ], - ), -] - -_RAW_RSA_KEYRINGS = [ - RawRSAKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_key=rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend()), - wrapping_algorithm=_WRAPPING_ALGORITHM, - ), - RawRSAKeyring.fromPEMEncoding( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - encoded_key=_PRIVATE_KEY, - password=None, - wrapping_algorithm=_WRAPPING_ALGORITHM, - ), - # RawRSAKeyring.fromDEREncoding( - # key_namespace=_PROVIDER_ID, - # key_name=_KEY_ID, - # encoded_key=b"-----BEGIN RSA PRIVATE KEY-----\n" - # b"MIIEowIBAAKCAQEAo8uCyhiO4JUGZV+rtNq5DBA9Lm4xkw5kTA3v6EPybs8bVXL2\n" - # b"ZE6jkbo+xT4Jg/bKzUpnp1fE+T1ruGPtsPdoEmhY/P64LDNIs3sRq5U4QV9IETU1\n" - # b"vIcbNNkgGhRjV8J87YNY0tV0H7tuWuZRpqnS+gjV6V9lUMkbvjMCc5IBqQc3heut\n" - # b"/+fH4JwpGlGxOVXI8QAapnSy1XpCr3+PT29kydVJnIMuAoFrurojRpOQbOuVvhtA\n" - # b"gARhst1Ji4nfROGYkj6eZhvkz2Bkud4/+3lGvVU5LO1vD8oY7WoGtpin3h50VcWe\n" - # b"aBT4kejx4s9/G9C4R24lTH09J9HO2UUsuCqZYQIDAQABAoIBAQCfC90bCk+qaWqF\n" - # b"gymC+qOWwCn4bM28gswHQb1D5r6AtKBRD8mKywVvWs7azguFVV3Fi8sspkBA2FBC\n" - # b"At5p6ULoJOTL/TauzLl6djVJTCMM701WUDm2r+ZOIctXJ5bzP4n5Q4I7b0NMEL7u\n" - # b"ixib4elYGr5D1vrVQAKtZHCr8gmkqyx8Mz7wkJepzBP9EeVzETCHsmiQDd5WYlO1\n" - # b"C2IQYgw6MJzgM4entJ0V/GPytkodblGY95ORVK7ZhyNtda+r5BZ6/jeMW+hA3VoK\n" - # b"tHSWjHt06ueVCCieZIATmYzBNt+zEz5UA2l7ksg3eWfVORJQS7a6Ef4VvbJLM9Ca\n" - # b"m1kdsjelAoGBANKgvRf39i3bSuvm5VoyJuqinSb/23IH3Zo7XOZ5G164vh49E9Cq\n" - # b"dOXXVxox74ppj/kbGUoOk+AvaB48zzfzNvac0a7lRHExykPH2kVrI/NwH/1OcT/x\n" - # b"2e2DnFYocXcb4gbdZQ+m6X3zkxOYcONRzPVW1uMrFTWHcJveMUm4PGx7AoGBAMcU\n" - # b"IRvrT6ye5se0s27gHnPweV+3xjsNtXZcK82N7duXyHmNjxrwOAv0SOhUmTkRXArM\n" - # b"6aN5D8vyZBSWma2TgUKwpQYFTI+4Sp7sdkkyojGAEixJ+c5TZJNxZFrUe0FwAoic\n" - # b"c2kb7ntaiEj5G+qHvykJJro5hy6uLnjiMVbAiJDTAoGAKb67241EmHAXGEwp9sdr\n" - # b"2SMjnIAnQSF39UKAthkYqJxa6elXDQtLoeYdGE7/V+J2K3wIdhoPiuY6b4vD0iX9\n" - # b"JcGM+WntN7YTjX2FsC588JmvbWfnoDHR7HYiPR1E58N597xXdFOzgUgORVr4PMWQ\n" - # b"pqtwaZO3X2WZlvrhr+e46hMCgYBfdIdrm6jYXFjL6RkgUNZJQUTxYGzsY+ZemlNm\n" - # b"fGdQo7a8kePMRuKY2MkcnXPaqTg49YgRmjq4z8CtHokRcWjJUWnPOTs8rmEZUshk\n" - # b"0KJ0mbQdCFt/Uv0mtXgpFTkEZ3DPkDTGcV4oR4CRfOCl0/EU/A5VvL/U4i/mRo7h\n" - # b"ye+xgQKBgD58b+9z+PR5LAJm1tZHIwb4tnyczP28PzwknxFd2qylR4ZNgvAUqGtU\n" - # b"xvpUDpzMioz6zUH9YV43YNtt+5Xnzkqj+u9Mr27/H2v9XPwORGfwQ5XPwRJz/2oC\n" - # b"EnPmP1SZoY9lXKUpQXHXSpDZ2rE2Klt3RHMUMHt8Zpy36E8Vwx8o\n" - # b"-----END RSA PRIVATE KEY-----\n", - # password=None, - # wrapping_algorithm=_WRAPPING_ALGORITHM, - # ) -] - - -@pytest.mark.parametrize("encryption_materials_samples", _ENCRYPTION_MATERIALS) -@pytest.mark.parametrize("fake_raw_rsa_keyring", _RAW_RSA_KEYRINGS) -def test_raw_rsa_encryption_decryption(encryption_materials_samples, fake_raw_rsa_keyring): - - # Call on_encrypt function for the keyring - encryption_materials = fake_raw_rsa_keyring.on_encrypt(encryption_materials=encryption_materials_samples) - - # Generate decryption materials - decryption_materials = DecryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, verification_key=b"ex_verification_key" - ) - - # Call on_decrypt function for the keyring - decryption_materials = fake_raw_rsa_keyring.on_decrypt( - decryption_materials=decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys - ) - - # if decryption_materials.data_encryption_key: - # # Check if the data keys match - assert encryption_materials.data_encryption_key == decryption_materials.data_encryption_key diff --git a/test/unit/test_keyring_base.py b/test/unit/test_keyring_base.py index 92241fd6a..439584bc1 100644 --- a/test/unit/test_keyring_base.py +++ b/test/unit/test_keyring_base.py @@ -38,23 +38,7 @@ algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, verification_key=b"ex_verification_key" ) -_encrypted_data_keys = [ - EncryptedDataKey( - key_provider=MasterKeyInfo(provider_id="Random Raw Keys", key_info=b"5325b043-5843-4629-869c-64794af77ada"), - encrypted_data_key=six.b( - "\n \x8b\xc6\xfd\x91\xc7\xd5\xdc+S\x15n\xd9P\x99n\x1d\xb2\xdd\x15\xeaW" - "\xc3\x13k2\xf6\x02\xd0\x0f\x85\xec\x9e\x12\xa7\x01\x01\x01\x01\x00x" - "\x8b\xc6\xfd\x91\xc7\xd5\xdc+S\x15n\xd9P\x99n\x1d\xb2\xdd\x15\xeaW" - "\xc3\x13k2\xf6\x02\xd0\x0f\x85\xec\x9e\x00\x00\x00~0|\x06\t*\x86H" - "\x86\xf7\r\x01\x07\x06\xa0o0m\x02\x01\x000h\x06\t*\x86H\x86\xf7\r" - "\x01\x07\x010\x1e\x06\t`\x86H\x01e\x03\x04\x01.0\x11\x04\x0c\xc9rP" - "\xa1\x08t6{\xf2\xfd\xf1\xb3\x02\x01\x10\x80;D\xa4\xed`qP~c\x0f\xa0d" - "\xd5\xa2Kj\xc7\xb2\xc6\x1e\xec\xfb\x0fK\xb2*\xd5\t2\x81pR\xee\xd1" - '\x1a\xde<"\x1b\x98\x88\x8b\xf4&\xdaB\x95I\xd2\xff\x10\x13\xfc\x1aX' - "\x08,/\x8b\x8b" - ), - ) -] +_encrypted_data_keys = [] class KeyringNoEncrypt(Keyring): @@ -68,9 +52,13 @@ def on_encrypt(self, _encryption_materials): def test_keyring_no_encrypt(): - assert pytest.raises(NotImplementedError) + with pytest.raises(NotImplementedError) as exc_info: + KeyringNoEncrypt().on_encrypt(encryption_materials=_encryption_materials) + assert exc_info.match("Keyring does not implement on_encrypt function") def test_keyring_no_decrypt(): - - assert pytest.raises(NotImplementedError) + with pytest.raises(NotImplementedError) as exc_info: + KeyringNoDecrypt().on_decrypt(decryption_materials=_decryption_materials, + encrypted_data_keys=_encrypted_data_keys) + assert exc_info.match("Keyring does not implement on_decrypt function") diff --git a/test/unit/test_keyring_raw_aes.py b/test/unit/test_keyring_raw_aes.py deleted file mode 100644 index 85b483b10..000000000 --- a/test/unit/test_keyring_raw_aes.py +++ /dev/null @@ -1,243 +0,0 @@ -# Copyright 2019 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. -"""Unit tests for Raw AES keyring.""" - -import pytest -import six -from mock import MagicMock, patch, sentinel - -from aws_encryption_sdk.exceptions import GenerateKeyError -from aws_encryption_sdk.identifiers import Algorithm, KeyringTraceFlag, WrappingAlgorithm -from aws_encryption_sdk.keyring.base import EncryptedDataKey, Keyring -from aws_encryption_sdk.keyring.raw_keyring import RawAESKeyring, generate_data_key -from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials -from aws_encryption_sdk.structures import KeyringTrace, MasterKeyInfo, RawDataKey - -from .test_values import VALUES -# from .test_utils import NullRawAESKeyring - -try: # Python 3.5.0 and 3.5.1 have incompatible typing modules - from typing import Iterable # noqa pylint: disable=unused-import -except ImportError: # pragma: no cover - # We only actually need these imports when running the mypy checks - pass - -pytestmark = [pytest.mark.unit, pytest.mark.local] - -_ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"} -_PROVIDER_ID = "Random Raw Keys" -_KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" -_WRAPPING_KEY = b"\xeby-\x80A6\x15rA8\x83#,\xe4\xab\xac`\xaf\x99Z\xc1\xce\xdb\xb6\x0f\xb7\x805\xb2\x14J3" -_SIGNING_KEY = b"aws-crypto-public-key" -_DATA_KEY = ( - b"\x00\xfa\x8c\xdd\x08Au\xc6\x92_4\xc5\xfb\x90\xaf\x8f\xa1D\xaf\xcc\xd25" b"\xa8\x0b\x0b\x16\x92\x91W\x01\xb7\x84" -) -_ENCRYPTION_MATERIALS_WITH_DATA_KEY = EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - keyring_trace=[ - KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}, - ) - ], -) - -_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY = EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, -) - -_ENCRYPTION_MATERIALS_WITH_ENCRYPTED_DATA_KEY = EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encrypted_data_keys=[ - EncryptedDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" - b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", - ) - ], - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - keyring_trace=[ - KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}, - ) - ], -) - -_DECRYPTION_MATERIALS_WITH_DATA_KEY = DecryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encryption_context=_ENCRYPTION_CONTEXT, - verification_key=b"ex_verification_key", - keyring_trace=[KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} - )] -) - -_DECRYPTION_MATERIALS_WITHOUT_DATA_KEY = DecryptionMaterials( - verification_key=b"ex_verification_key", -) - - -class TestRawAESKeyring(object): - @pytest.fixture(autouse=True) - def apply_fixtures(self): - self.mock_encrypted_data_key = EncryptedDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - encrypted_data_key=VALUES["encrypted_data_key"], - ) - self.mock_encryption_materials = MagicMock() - self.mock_encryption_materials.__class__ = EncryptionMaterials - - def test_parent(self): - assert issubclass(RawAESKeyring, Keyring) - - # def test_initialization(self): - # test = RawAESKeyring( - # key_namespace=_PROVIDER_ID, - # key_name=_KEY_ID, - # wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, - # wrapping_key=_WRAPPING_KEY, - # ) - # assert test.__getattribute__(key_provider) == self.mock_encrypted_data_key.key_provider - - @patch("aws_encryption_sdk.keyring.raw_keyring.generate_data_key") - def test_data_encryption_key_provided(self, mock_generate_data_key): - mock_generate_data_key.return_value = _DATA_KEY - test_raw_aes_keyring = RawAESKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, - wrapping_key=_WRAPPING_KEY, - ) - - test = test_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITH_DATA_KEY) - # Check if keyring is generated - assert not mock_generate_data_key.called - - # Check if data encryption key is encrypted - assert test.encrypted_data_keys is not None - - def test_data_encryption_key_generated(self): - test_raw_aes_keyring = RawAESKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, - wrapping_key=_WRAPPING_KEY, - ) - test = test_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY) - - # Check if key is generated - if not test.data_encryption_key: - # Check if error thrown if data key is not generated - assert pytest.raises(GenerateKeyError, "Unable to generate data encryption key.") - else: - # Check if data key is generated - assert test.data_encryption_key and test.data_encryption_key is not None - assert test.encrypted_data_keys and test.encrypted_data_keys is not None - - @patch("aws_encryption_sdk.keyring.raw_keyring.generate_data_key") - def test_encrypted_data_key_provided(self, mock_generate_data_key): - mock_generate_data_key.return_value = _DATA_KEY - test_raw_aes_keyring = RawAESKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, - wrapping_key=_WRAPPING_KEY, - ) - test = test_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITH_ENCRYPTED_DATA_KEY) - - # Check if generate_data_key is called - assert not mock_generate_data_key.called - # - # Check if encrypt is called - assert len(test.encrypted_data_keys) == len(_ENCRYPTION_MATERIALS_WITH_ENCRYPTED_DATA_KEY.encrypted_data_keys) - - # @patch("aws_encryption_sdk.key_providers.raw.os.urandom") - # def test_data_key_not_generated(self, mock_os_urandom): - # mock_os_urandom.return_value = None - # test_raw_aes_keyring = RawAESKeyring( - # key_namespace=_PROVIDER_ID, - # key_name=_KEY_ID, - # wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, - # wrapping_key=_WRAPPING_KEY, - # ) - # test = test_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY) - # assert pytest.raises(GenerateKeyError, "Unable to generate data encryption key.") - - @patch("aws_encryption_sdk.keyring.raw_keyring.generate_data_key") - def test_data_key_not_generated(self, mock_generate_data_key): - mock_generate_data_key.return_value = None - test_raw_aes_keyring = RawAESKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, - wrapping_key=_WRAPPING_KEY, - ) - test = test_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY) - assert pytest.raises(GenerateKeyError) - - @patch("aws_encryption_sdk.internal.crypto.wrapping_keys.WrappingKey.decrypt") - def test_decrypt_when_data_key_provided(self, mock_decrypt): - mock_decrypt.return_value = _DATA_KEY - test_raw_aes_keyring = RawAESKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, - wrapping_key=_WRAPPING_KEY, - ) - test = test_raw_aes_keyring.on_decrypt(decryption_materials=_DECRYPTION_MATERIALS_WITH_DATA_KEY, - encrypted_data_keys=[self.mock_encrypted_data_key]) - assert not mock_decrypt.called - - # @patch("aws_encryption_sdk.internal.crypto.wrapping_keys.WrappingKey.decrypt") - # def test_decrypt_when_data_key_not_provided(self, mock_decrypt): - # mock_decrypt.return_value = _DATA_KEY - # test_raw_aes_keyring = RawAESKeyring( - # key_namespace=_PROVIDER_ID, - # key_name=_KEY_ID, - # wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, - # wrapping_key=_WRAPPING_KEY, - # ) - # - # test = test_raw_aes_keyring.on_decrypt(decryption_materials=_DECRYPTION_MATERIALS_WITHOUT_DATA_KEY, - # encrypted_data_keys=[ - # EncryptedDataKey( - # key_provider=MasterKeyInfo( - # provider_id=_PROVIDER_ID, - # key_info=_KEY_ID), - # encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\ - # xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" - # b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\ - # x07FzE\xde", - # ) - # ] - # ) - # assert mock_decrypt.called diff --git a/test/unit/test_keyring_raw_rsa.py b/test/unit/test_keyring_raw_rsa.py deleted file mode 100644 index 532cfc01e..000000000 --- a/test/unit/test_keyring_raw_rsa.py +++ /dev/null @@ -1,244 +0,0 @@ -# Copyright 2019 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. -"""Unit tests for Raw AES keyring.""" - -import pytest -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives.asymmetric import rsa -from mock import MagicMock, patch, sentinel - -from aws_encryption_sdk.exceptions import GenerateKeyError -from aws_encryption_sdk.identifiers import Algorithm, KeyringTraceFlag, WrappingAlgorithm -from aws_encryption_sdk.keyring.base import EncryptedDataKey, Keyring -from aws_encryption_sdk.keyring.raw_keyring import RawRSAKeyring, generate_data_key -from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials -from aws_encryption_sdk.structures import KeyringTrace, MasterKeyInfo, RawDataKey - -from .test_values import VALUES -# from .test_utils import NullRawAESKeyring - -try: # Python 3.5.0 and 3.5.1 have incompatible typing modules - from typing import Iterable # noqa pylint: disable=unused-import -except ImportError: # pragma: no cover - # We only actually need these imports when running the mypy checks - pass - -pytestmark = [pytest.mark.unit, pytest.mark.local] - -_ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"} -_PROVIDER_ID = "Random Raw Keys" -_KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" -_WRAPPING_KEY = rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend()) -_SIGNING_KEY = b"aws-crypto-public-key" -_DATA_KEY = ( - b"\x00\xfa\x8c\xdd\x08Au\xc6\x92_4\xc5\xfb\x90\xaf\x8f\xa1D\xaf\xcc\xd25" b"\xa8\x0b\x0b\x16\x92\x91W\x01\xb7\x84" -) -_ENCRYPTION_MATERIALS_WITH_DATA_KEY = EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - keyring_trace=[ - KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY}, - ) - ], -) - -_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY = EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, -) - -_ENCRYPTION_MATERIALS_WITH_ENCRYPTED_DATA_KEY = EncryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encrypted_data_keys=[ - EncryptedDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" - b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", - ) - ], - encryption_context=_ENCRYPTION_CONTEXT, - signing_key=_SIGNING_KEY, - keyring_trace=[ - KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY, KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY}, - ) - ], -) - -_DECRYPTION_MATERIALS_WITH_DATA_KEY = DecryptionMaterials( - algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - data_encryption_key=RawDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - data_key=b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', - ), - encryption_context=_ENCRYPTION_CONTEXT, - verification_key=b"ex_verification_key", - keyring_trace=[KeyringTrace( - wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - flags={KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY} - )] -) - -_DECRYPTION_MATERIALS_WITHOUT_DATA_KEY = DecryptionMaterials( - verification_key=b"ex_verification_key", -) - - -class TestRawRSAKeyring(object): - @pytest.fixture(autouse=True) - def apply_fixtures(self): - self.mock_encrypted_data_key = EncryptedDataKey( - key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), - encrypted_data_key=VALUES["encrypted_data_key"], - ) - self.mock_encryption_materials = MagicMock() - self.mock_encryption_materials.__class__ = EncryptionMaterials - - def test_parent(self): - assert issubclass(RawRSAKeyring, Keyring) - - # def test_initialization(self): - # test = RawAESKeyring( - # key_namespace=_PROVIDER_ID, - # key_name=_KEY_ID, - # wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, - # wrapping_key=_WRAPPING_KEY, - # ) - # assert test.__getattribute__(key_provider) == self.mock_encrypted_data_key.key_provider - - @patch("aws_encryption_sdk.keyring.raw_keyring.generate_data_key") - def test_data_encryption_key_provided(self, mock_generate_data_key): - mock_generate_data_key.return_value = _DATA_KEY - test_raw_rsa_keyring = RawRSAKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, - wrapping_key=_WRAPPING_KEY, - ) - - test = test_raw_rsa_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITH_DATA_KEY) - # Check if keyring is generated - assert not mock_generate_data_key.called - - # Check if data encryption key is encrypted - assert test.encrypted_data_keys is not None - - def test_data_encryption_key_generated(self): - test_raw_rsa_keyring = RawRSAKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, - wrapping_key=_WRAPPING_KEY, - ) - test = test_raw_rsa_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY) - - # Check if key is generated - if not test.data_encryption_key: - # Check if error thrown if data key is not generated - assert pytest.raises(GenerateKeyError, "Unable to generate data encryption key.") - else: - # Check if data key is generated - assert test.data_encryption_key and test.data_encryption_key is not None - assert test.encrypted_data_keys and test.encrypted_data_keys is not None - - @patch("aws_encryption_sdk.keyring.raw_keyring.generate_data_key") - def test_encrypted_data_key_provided(self, mock_generate_data_key): - mock_generate_data_key.return_value = _DATA_KEY - test_raw_rsa_keyring = RawRSAKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, - wrapping_key=_WRAPPING_KEY, - ) - test = test_raw_rsa_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITH_ENCRYPTED_DATA_KEY) - - # Check if generate_data_key is called - assert not mock_generate_data_key.called - # - # Check if encrypt is called - assert len(test.encrypted_data_keys) == len(_ENCRYPTION_MATERIALS_WITH_ENCRYPTED_DATA_KEY.encrypted_data_keys) - - # @patch("aws_encryption_sdk.key_providers.raw.os.urandom") - # def test_data_key_not_generated(self, mock_os_urandom): - # mock_os_urandom.return_value = None - # test_raw_aes_keyring = RawAESKeyring( - # key_namespace=_PROVIDER_ID, - # key_name=_KEY_ID, - # wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, - # wrapping_key=_WRAPPING_KEY, - # ) - # test = test_raw_aes_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY) - # assert pytest.raises(GenerateKeyError, "Unable to generate data encryption key.") - - @patch("aws_encryption_sdk.keyring.raw_keyring.generate_data_key") - def test_data_key_not_generated(self, mock_generate_data_key): - mock_generate_data_key.return_value = None - test_raw_rsa_keyring = RawRSAKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, - wrapping_key=_WRAPPING_KEY, - ) - test = test_raw_rsa_keyring.on_encrypt(encryption_materials=_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY) - assert pytest.raises(GenerateKeyError) - - @patch("aws_encryption_sdk.internal.crypto.wrapping_keys.WrappingKey.decrypt") - def test_decrypt_when_data_key_provided(self, mock_decrypt): - mock_decrypt.return_value = _DATA_KEY - test_raw_rsa_keyring = RawRSAKeyring( - key_namespace=_PROVIDER_ID, - key_name=_KEY_ID, - wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, - wrapping_key=_WRAPPING_KEY, - ) - test = test_raw_rsa_keyring.on_decrypt(decryption_materials=_DECRYPTION_MATERIALS_WITH_DATA_KEY, - encrypted_data_keys=[self.mock_encrypted_data_key]) - assert not mock_decrypt.called - - # @patch("aws_encryption_sdk.internal.crypto.wrapping_keys.WrappingKey.decrypt") - # def test_decrypt_when_data_key_not_provided(self, mock_decrypt): - # mock_decrypt.return_value = _DATA_KEY - # test_raw_aes_keyring = RawAESKeyring( - # key_namespace=_PROVIDER_ID, - # key_name=_KEY_ID, - # wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, - # wrapping_key=_WRAPPING_KEY, - # ) - # - # test = test_raw_aes_keyring.on_decrypt(decryption_materials=_DECRYPTION_MATERIALS_WITHOUT_DATA_KEY, - # encrypted_data_keys=[ - # EncryptedDataKey( - # key_provider=MasterKeyInfo( - # provider_id=_PROVIDER_ID, - # key_info=_KEY_ID), - # encrypted_data_key=b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\ - # xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" - # b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\ - # x07FzE\xde", - # ) - # ] - # ) - # assert mock_decrypt.called diff --git a/test/unit/test_utils.py b/test/unit/test_utils.py index 0cb244fb2..d20484bd9 100644 --- a/test/unit/test_utils.py +++ b/test/unit/test_utils.py @@ -21,9 +21,7 @@ import aws_encryption_sdk.internal.utils from aws_encryption_sdk.exceptions import InvalidDataKeyError, SerializationError, UnknownIdentityError from aws_encryption_sdk.internal.defaults import MAX_FRAME_SIZE, MESSAGE_ID_LENGTH -from aws_encryption_sdk.materials_managers import EncryptionMaterials, DecryptionMaterials, EncryptedDataKey from aws_encryption_sdk.structures import DataKey, EncryptedDataKey, MasterKeyInfo, RawDataKey -from aws_encryption_sdk.keyring.raw_keyring import RawRSAKeyring, RawAESKeyring from .test_values import VALUES from .unit_test_utils import assert_prepped_stream_identity @@ -50,16 +48,6 @@ def test_prep_stream_data_wrap(source): assert_prepped_stream_identity(test, io.BytesIO) -class NullRawRSAKeyring(RawRSAKeyring): - def on_encrypt(self, encryption_materials): - # type: (EncryptionMaterials) -> EncryptionMaterials - return encryption_materials - - def on_decrypt(self, decryption_materials, encrypted_data_keys): - # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials - return decryption_materials - - class TestUtils(object): @pytest.fixture(autouse=True) def apply_fixtures(self): From 115254be9515140b984ca68f19a8d5b1e446f3fb Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 23 Jul 2019 18:39:24 -0700 Subject: [PATCH 104/110] Made suggested changes to base API tests --- test/unit/test_keyring_base.py | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/test/unit/test_keyring_base.py b/test/unit/test_keyring_base.py index 439584bc1..4b6e318eb 100644 --- a/test/unit/test_keyring_base.py +++ b/test/unit/test_keyring_base.py @@ -41,24 +41,13 @@ _encrypted_data_keys = [] -class KeyringNoEncrypt(Keyring): - def on_decrypt(self, _decryption_materials, _encrypted_data_keys): - return _decryption_materials - - -class KeyringNoDecrypt(Keyring): - def on_encrypt(self, _encryption_materials): - return _encryption_materials - - def test_keyring_no_encrypt(): with pytest.raises(NotImplementedError) as exc_info: - KeyringNoEncrypt().on_encrypt(encryption_materials=_encryption_materials) + Keyring().on_encrypt(encryption_materials=_encryption_materials) assert exc_info.match("Keyring does not implement on_encrypt function") def test_keyring_no_decrypt(): with pytest.raises(NotImplementedError) as exc_info: - KeyringNoDecrypt().on_decrypt(decryption_materials=_decryption_materials, - encrypted_data_keys=_encrypted_data_keys) + Keyring().on_decrypt(decryption_materials=_decryption_materials, encrypted_data_keys=_encrypted_data_keys) assert exc_info.match("Keyring does not implement on_decrypt function") From b37933cebf04bf193c078e30620cd67462dfb790 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 23 Jul 2019 18:42:05 -0700 Subject: [PATCH 105/110] Ignore commit --- test/unit/test_utils.py | 1 - test/unit/test_values.py | 7 ++++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/unit/test_utils.py b/test/unit/test_utils.py index d20484bd9..fa737805d 100644 --- a/test/unit/test_utils.py +++ b/test/unit/test_utils.py @@ -271,4 +271,3 @@ def test_source_data_key_length_check_invalid(self): source_data_key=mock_data_key, algorithm=mock_algorithm ) excinfo.match("Invalid Source Data Key length 4 for algorithm required: 5") - diff --git a/test/unit/test_values.py b/test/unit/test_values.py index acd09db2a..b9aba0c02 100644 --- a/test/unit/test_values.py +++ b/test/unit/test_values.py @@ -189,7 +189,8 @@ def array_byte(source): "signature_len": b"\x00h", "private_rsa_key_bytes": [ ( - b"-----BEGIN RSA PRIVATE KEY-----"b"MIICXgIBAAKBgQCUjhI8YRPXV8Gfofbg/" + b"-----BEGIN RSA PRIVATE KEY-----" + b"MIICXgIBAAKBgQCUjhI8YRPXV8Gfofbg/" b"PLjWw2AzowQTPErLU2z3+xGqElMdzdiC4Ta43DFWZg34Eg0X8kQPAeoe8h3cRSMo" b"77eSOHt2dPo7OfTfZqsH8766fivHIKVxBYPX8SZYIUhMtRnlg3uqch9BksfRop+h" b"f8h/H3lfervJoevS2CXYB9/iwIDAQABAoGBAIqeGzQOHbaGI51yQ2zjez1dPDdiB" @@ -233,8 +234,8 @@ def array_byte(source): b"xvpUDpzMioz6zUH9YV43YNtt+5Xnzkqj+u9Mr27/H2v9XPwORGfwQ5XPwRJz/2oC\n" b"EnPmP1SZoY9lXKUpQXHXSpDZ2rE2Klt3RHMUMHt8Zpy36E8Vwx8o\n" b"-----END RSA PRIVATE KEY-----\n" - ) - ] + ), + ], } VALUES["updated_encryption_context"] = copy.deepcopy(VALUES["encryption_context"]) VALUES["updated_encryption_context"]["aws-crypto-public-key"] = VALUES["encoded_curve_point"] From a7eb7e20184fc8ff0afa3cb58ec255754722f494 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Tue, 23 Jul 2019 22:40:26 -0700 Subject: [PATCH 106/110] Corrected tox and pylint errors in base API unit tests --- test/unit/test_keyring_base.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/unit/test_keyring_base.py b/test/unit/test_keyring_base.py index 4b6e318eb..33836675f 100644 --- a/test/unit/test_keyring_base.py +++ b/test/unit/test_keyring_base.py @@ -13,12 +13,10 @@ """Unit tests for base keyring.""" import pytest -import six from aws_encryption_sdk.identifiers import Algorithm -from aws_encryption_sdk.keyring.base import EncryptedDataKey, Keyring +from aws_encryption_sdk.keyring.base import Keyring from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials -from aws_encryption_sdk.structures import MasterKeyInfo try: # Python 3.5.0 and 3.5.1 have incompatible typing modules from typing import Iterable # noqa pylint: disable=unused-import From 5a9d2bb6ecb226f576ea73369dbdb01eb89cb05c Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Wed, 31 Jul 2019 17:14:47 -0700 Subject: [PATCH 107/110] Removed try except for Iterable --- src/aws_encryption_sdk/keyring/base.py | 6 ------ test/unit/test_keyring_base.py | 5 ----- 2 files changed, 11 deletions(-) diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index 770b53c0b..a95c770c8 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -14,12 +14,6 @@ from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials from aws_encryption_sdk.structures import EncryptedDataKey -try: # Python 3.5.0 and 3.5.1 have incompatible typing modules - from typing import Iterable # noqa pylint: disable=unused-import -except ImportError: # pragma: no cover - # We only actually need these imports when running the mypy checks - pass - class Keyring(object): """Parent interface for Keyring classes. diff --git a/test/unit/test_keyring_base.py b/test/unit/test_keyring_base.py index 33836675f..8919c0142 100644 --- a/test/unit/test_keyring_base.py +++ b/test/unit/test_keyring_base.py @@ -18,11 +18,6 @@ from aws_encryption_sdk.keyring.base import Keyring from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials -try: # Python 3.5.0 and 3.5.1 have incompatible typing modules - from typing import Iterable # noqa pylint: disable=unused-import -except ImportError: # pragma: no cover - # We only actually need these imports when running the mypy checks - pass pytestmark = [pytest.mark.unit, pytest.mark.local] From 0767416ff18ecde81ed3a483120942cc3e15d4c8 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Wed, 31 Jul 2019 17:15:51 -0700 Subject: [PATCH 108/110] Removed try except for Iterable from test_utils --- test/unit/test_utils.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/unit/test_utils.py b/test/unit/test_utils.py index fa737805d..76cbdc53b 100644 --- a/test/unit/test_utils.py +++ b/test/unit/test_utils.py @@ -26,11 +26,6 @@ from .test_values import VALUES from .unit_test_utils import assert_prepped_stream_identity -try: # Python 3.5.0 and 3.5.1 have incompatible typing modules - from typing import Iterable # noqa pylint: disable=unused-import -except ImportError: # pragma: no cover - # We only actually need these imports when running the mypy checks - pass pytestmark = [pytest.mark.unit, pytest.mark.local] From 66d96c29b2e56bc79cce34a5333a84c32edceffa Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Wed, 31 Jul 2019 17:57:55 -0700 Subject: [PATCH 109/110] Added try except for Iterable in base API --- src/aws_encryption_sdk/keyring/base.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/aws_encryption_sdk/keyring/base.py b/src/aws_encryption_sdk/keyring/base.py index a95c770c8..770b53c0b 100644 --- a/src/aws_encryption_sdk/keyring/base.py +++ b/src/aws_encryption_sdk/keyring/base.py @@ -14,6 +14,12 @@ from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials from aws_encryption_sdk.structures import EncryptedDataKey +try: # Python 3.5.0 and 3.5.1 have incompatible typing modules + from typing import Iterable # noqa pylint: disable=unused-import +except ImportError: # pragma: no cover + # We only actually need these imports when running the mypy checks + pass + class Keyring(object): """Parent interface for Keyring classes. From 28fdbd8221d8a8829cd841816fd9d82483f5ab66 Mon Sep 17 00:00:00 2001 From: Megha Vasant Shetty Date: Wed, 31 Jul 2019 18:06:53 -0700 Subject: [PATCH 110/110] Resolved isort errors --- test/unit/test_keyring_base.py | 1 - test/unit/test_utils.py | 1 - 2 files changed, 2 deletions(-) diff --git a/test/unit/test_keyring_base.py b/test/unit/test_keyring_base.py index 8919c0142..70863de53 100644 --- a/test/unit/test_keyring_base.py +++ b/test/unit/test_keyring_base.py @@ -18,7 +18,6 @@ from aws_encryption_sdk.keyring.base import Keyring from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials - pytestmark = [pytest.mark.unit, pytest.mark.local] _encryption_materials = EncryptionMaterials( diff --git a/test/unit/test_utils.py b/test/unit/test_utils.py index 76cbdc53b..b1374a09d 100644 --- a/test/unit/test_utils.py +++ b/test/unit/test_utils.py @@ -26,7 +26,6 @@ from .test_values import VALUES from .unit_test_utils import assert_prepped_stream_identity - pytestmark = [pytest.mark.unit, pytest.mark.local]