From f1fca97b65e27cf45147f0bd8e19f8415369654b Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Thu, 6 Jun 2024 11:48:27 -0700 Subject: [PATCH 01/11] chore(migration examples): added KMS, raw AES and raw RSA keyring/MKP examples --- ...migration_set_commitment_policy_example.py | 0 ...rom_aws_kms_master_key_provider_example.py | 274 ++++++++++++++ ...rom_raw_aes_master_key_provider_example.py | 288 ++++++++++++++ ...rom_raw_rsa_master_key_provider_example.py | 358 ++++++++++++++++++ examples/test/migration/__init__.py | 3 + ...migration_set_commitment_policy_example.py | 2 +- ...rom_aws_kms_master_key_provider_example.py | 16 + ...rom_raw_aes_master_key_provider_example.py | 15 + ...rom_raw_rsa_master_key_provider_example.py | 15 + 9 files changed, 970 insertions(+), 1 deletion(-) rename examples/src/{ => migration}/migration_set_commitment_policy_example.py (100%) create mode 100644 examples/src/migration/migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py create mode 100644 examples/src/migration/migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py create mode 100644 examples/src/migration/migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py create mode 100644 examples/test/migration/__init__.py rename examples/test/{ => migration}/test_i_migration_set_commitment_policy_example.py (83%) create mode 100644 examples/test/migration/test_i_migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py create mode 100644 examples/test/migration/test_i_migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py create mode 100644 examples/test/migration/test_i_migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py diff --git a/examples/src/migration_set_commitment_policy_example.py b/examples/src/migration/migration_set_commitment_policy_example.py similarity index 100% rename from examples/src/migration_set_commitment_policy_example.py rename to examples/src/migration/migration_set_commitment_policy_example.py diff --git a/examples/src/migration/migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py b/examples/src/migration/migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py new file mode 100644 index 000000000..64f774a37 --- /dev/null +++ b/examples/src/migration/migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py @@ -0,0 +1,274 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This is a migration example for moving to the AWS KMS Keyring from AWS KMS master key provider (MKP) + +The AWS KMS keyring uses symmetric encryption KMS keys to generate, encrypt and +decrypt data keys. This example defines classes for KMS Keyring and KMS MKP and +then encrypts a custom input EXAMPLE_DATA with an encryption context using both +the keyring and MKP. The example then decrypts the ciphertext using both keyring and MKPs. +This example also includes some sanity checks for demonstration: +1. Decryption of these ciphertexts encrypted using keyring and MKP + is possible using both KMS keyring and KMS MKP +2. Both decrypted plaintexts are same and match EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP are not +the same because the ESDK generates different data keys each time for encryption of the data. +But both ciphertexts when decrypted using keyring and MKP should give the same plaintext result. + +For more information on how to use KMS keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html +""" + +import boto3 +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict # noqa pylint: disable=wrong-import-order + +import aws_encryption_sdk + +EXAMPLE_DATA: bytes = b"Hello World" + +DEFAULT_ENCRYPTION_CONTEXT : Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", +} + + +class AwsKmsKeyring(): + """Class for creating a KMS Keyring and using it for encryption and decryption""" + + @staticmethod + def create_kms_client(aws_region="us-west-2"): + """Create an AWS KMS client. + + Usage: create_kms_client(aws_region) + :param aws_region: AWS region to use for KMS client. + :type aws_region: string + """ + # Create a boto3 client for KMS. + kms_client = boto3.client('kms', region_name=aws_region) + + return kms_client + + @staticmethod + def create_keyring( + kms_key_id: str + ): + """Demonstrate how to create an AWS KMS keyring. + + Usage: create_keyring(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # Create a boto3 client for KMS. + kms_client = AwsKmsKeyring.create_kms_client() + + # Create a KMS keyring + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=kms_key_id, + kms_client=kms_client + ) + + keyring: IKeyring = mat_prov.create_aws_kms_keyring( + input=keyring_input + ) + + return keyring + + @staticmethod + def encrypt_using_keyring( + plaintext_data: bytes, + keyring: IKeyring + ): + """Demonstrate how to encrypt plaintext data using an AWS KMS keyring. + + Usage: encrypt_using_keyring(plaintext_data, keyring) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param keyring: Keyring to use for encryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + keyring=keyring, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + return ciphertext_data + + @staticmethod + def decrypt_using_keyring( + ciphertext_data: bytes, + keyring: IKeyring + ): + """Demonstrate how to decrypt ciphertext data using an AWS KMS keyring. + + Usage: decrypt_using_keyring(ciphertext_data, keyring) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param keyring: Keyring to use for decryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + keyring=keyring + ) + + return decrypted_plaintext_data + + +class AwsKmsMasterKeyProvider(): + """Class for creating a KMS MKP and using it for encryption and decryption""" + + @staticmethod + def create_key_provider( + kms_key_id: str + ): + """Demonstrate how to create an AWS KMS master key provider. + + Usage: create_key_provider(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # Create a KMS master key provider. + key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[ + kms_key_id, + ]) + + return key_provider + + @staticmethod + def encrypt_using_key_provider( + plaintext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + ): + """Demonstrate how to encrypt plaintext data using an AWS KMS master key provider. + + Usage: encrypt_using_key_provider(plaintext_data, key_provider) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param key_provider: Master key provider to use for encryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + key_provider=key_provider, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + return ciphertext_data + + @staticmethod + def decrypt_using_key_provider( + ciphertext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + ): + """Demonstrate how to decrypt ciphertext data using an AWS KMS master key provider. + + Usage: decrypt_using_key_provider(ciphertext_data, key_provider) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param key_provider: Master key provider to use for decryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + key_provider=key_provider + ) + + return decrypted_plaintext_data + + +def migration_to_aws_kms_keyring_from_aws_kms_master_key_provider( + kms_key_id: str +): + """Demonstrate a migration example for moving from an AWS KMS keyring to AWS KMS MKP. + + Usage: migration_to_aws_kms_keyring_from_aws_kms_master_key_provider(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use for encryption and + decryption of your data keys. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + + # 1a. Create a AWS KMS Keyring + aws_kms_keyring = AwsKmsKeyring.create_keyring(kms_key_id=kms_key_id) + + # 1b. Create a AWS KMS Master Key Provider + aws_kms_master_key_provider = AwsKmsMasterKeyProvider.create_key_provider(kms_key_id=kms_key_id) + + # 2a. Encrypt EXAMPLE_DATA using AWS KMS Keyring + ciphertext_keyring = AwsKmsKeyring.encrypt_using_keyring( + plaintext_data=EXAMPLE_DATA, + keyring=aws_kms_keyring + ) + + # 2b. Encrypt EXAMPLE_DATA using AWS KMS Master Key Provider + ciphertext_mkp = AwsKmsMasterKeyProvider.encrypt_using_key_provider( + plaintext_data=EXAMPLE_DATA, + key_provider=aws_kms_master_key_provider + ) + + # Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP + # (that is ciphertext_keyring and ciphertext_mkp) are not the same because the ESDK + # generates different data keys each time for encryption of the data. But both + # ciphertexts when decrypted using keyring and MKP should give the same plaintext result. + + # 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_keyring_using_keyring = AwsKmsKeyring.decrypt_using_keyring( + ciphertext_data=ciphertext_keyring, + keyring=aws_kms_keyring + ) + + decrypted_ciphertext_keyring_using_mkp = AwsKmsMasterKeyProvider.decrypt_using_key_provider( + ciphertext_data=ciphertext_keyring, + key_provider=aws_kms_master_key_provider + ) + + assert decrypted_ciphertext_keyring_using_keyring == decrypted_ciphertext_keyring_using_mkp \ + and decrypted_ciphertext_keyring_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" + + # 4. Decrypt the ciphertext_mkp using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_mkp_using_keyring = AwsKmsKeyring.decrypt_using_keyring( + ciphertext_data=ciphertext_mkp, + keyring=aws_kms_keyring + ) + + decrypted_ciphertext_mkp_using_mkp = AwsKmsMasterKeyProvider.decrypt_using_key_provider( + ciphertext_data=ciphertext_mkp, + key_provider=aws_kms_master_key_provider + ) + + assert decrypted_ciphertext_mkp_using_keyring == decrypted_ciphertext_mkp_using_mkp \ + and decrypted_ciphertext_mkp_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" diff --git a/examples/src/migration/migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py b/examples/src/migration/migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py new file mode 100644 index 000000000..289569e05 --- /dev/null +++ b/examples/src/migration/migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py @@ -0,0 +1,288 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This is a migration example for moving to the Raw AES Keyring from Raw AES master key provider (MKP) + +The Raw AES keyring lets you use an AES symmetric key that you provide as a wrapping key that +protects your data key. You need to generate, store, and protect the key material, +preferably in a hardware security module (HSM) or key management system. Use a Raw AES keyring +when you need to provide the wrapping key and encrypt the data keys locally or offline. + +This example defines classes for Raw AES Keyring and Raw AES MKP and +then encrypts a custom input EXAMPLE_DATA with an encryption context using both +the keyring and MKP. The example then decrypts the ciphertext using both keyring and MKPs. +This example also includes some sanity checks for demonstration: +1. Decryption of these ciphertexts encrypted using keyring and MKP + is possible using both KMS keyring and KMS MKP +2. Both decrypted plaintexts are same and match EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP are not +the same because the ESDK generates different data keys each time for encryption of the data. +But both ciphertexts when decrypted using keyring and MKP should give the same plaintext result. + +For more information on how to use Raw AES keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html +""" + +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import AesWrappingAlg, CreateRawAesKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict # noqa pylint: disable=wrong-import-order + +import aws_encryption_sdk +from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm +from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey +from aws_encryption_sdk.key_providers.raw import RawMasterKeyProvider + +EXAMPLE_DATA: bytes = b"Hello World" + +DEFAULT_ENCRYPTION_CONTEXT : Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", +} + +DEFAULT_AES_256_STATIC_KEY = \ + b'_\xcf"\x82\x03\x12\x9d\x00\x8a\xed\xaf\xe4\x80\x1d\x00t\xa6P\xac\xb6\xfe\xc5\xf6/{\xe7\xaaO\x01\x13W\x85' + +DEFAULT_KEY_NAME_SPACE = "Some managed raw keys" + +DEFAULT_KEY_NAME = "My 256-bit AES wrapping key" + + +class RawAesKeyring(): + """Class for creating a Raw AES Keyring and using it for encryption and decryption""" + + @staticmethod + def create_keyring(): + """Demonstrate how to create a Raw AES keyring. + + Usage: create_keyring() + """ + # We fix the static key in order to make the test deterministic + static_key = DEFAULT_AES_256_STATIC_KEY + + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateRawAesKeyringInput = CreateRawAesKeyringInput( + key_namespace=DEFAULT_KEY_NAME_SPACE, + key_name=DEFAULT_KEY_NAME, + wrapping_key=static_key, + wrapping_alg=AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16 + ) + + keyring: IKeyring = mat_prov.create_raw_aes_keyring( + input=keyring_input + ) + + return keyring + + @staticmethod + def encrypt_using_keyring( + plaintext_data: bytes, + keyring: IKeyring + ): + """Demonstrate how to encrypt plaintext data using a Raw AES keyring. + + Usage: encrypt_using_keyring(plaintext_data, keyring) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param keyring: Keyring to use for encryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + keyring=keyring, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + return ciphertext_data + + @staticmethod + def decrypt_using_keyring( + ciphertext_data: bytes, + keyring: IKeyring + ): + """Demonstrate how to decrypt ciphertext data using a Raw AES keyring. + + Usage: decrypt_using_keyring(ciphertext_data, keyring) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param keyring: Keyring to use for decryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + keyring=keyring + ) + + return decrypted_plaintext_data + + +# This is a helper class necessary for the Raw AES master key provider +class StaticRandomMasterKeyProvider(RawMasterKeyProvider): + """Generates 256-bit keys for each unique key ID.""" + + # The Provider ID (or Provider) field in the JceMasterKey and RawMasterKey is + # equivalent to key namespace in the Raw keyrings + provider_id = DEFAULT_KEY_NAME_SPACE + + def __init__(self, **kwargs): # pylint: disable=unused-argument + """Initialize empty map of keys.""" + self._static_keys = {} + + def _get_raw_key(self, key_id): + """Returns a static, randomly-generated symmetric key for the specified key ID. + + :param str key_id: Key ID + :returns: Wrapping key that contains the specified static key + :rtype: :class:`aws_encryption_sdk.internal.crypto.WrappingKey` + """ + try: + static_key = self._static_keys[key_id] + except KeyError: + # We fix the static key in order to make the test deterministic + # In practice, you should get this key from a secure key management system such as an HSM. + static_key = DEFAULT_AES_256_STATIC_KEY + self._static_keys[key_id] = static_key + return WrappingKey( + wrapping_algorithm=WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING, + wrapping_key=static_key, + wrapping_key_type=EncryptionKeyType.SYMMETRIC, + ) + + +class RawAesMasterKeyProvider(): + """Class for creating a Raw AES MKP and using it for encryption and decryption""" + + @staticmethod + def create_key_provider(): + """Demonstrate how to create a Raw AES master key provider. + + Usage: create_key_provider() + """ + # Create a Raw AES master key provider. + + # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name in the Raw keyrings + key_id = DEFAULT_KEY_NAME + key_provider = StaticRandomMasterKeyProvider() + key_provider.add_master_key(key_id) + + return key_provider + + @staticmethod + def encrypt_using_key_provider( + plaintext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + ): + """Demonstrate how to encrypt plaintext data using a Raw AES master key provider. + + Usage: encrypt_using_key_provider(plaintext_data, key_provider) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param key_provider: Master key provider to use for encryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + key_provider=key_provider, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + return ciphertext_data + + @staticmethod + def decrypt_using_key_provider( + ciphertext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + ): + """Demonstrate how to decrypt ciphertext data using a Raw AES master key provider. + + Usage: decrypt_using_key_provider(ciphertext_data, key_provider) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param key_provider: Master key provider to use for decryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + key_provider=key_provider + ) + + return decrypted_plaintext_data + + +def migration_to_raw_aes_keyring_from_raw_aes_master_key_provider(): + """Demonstrate a migration example for moving from a Raw AES keyring to Raw AES MKP. + + Usage: migration_to_raw_aes_keyring_from_raw_aes_master_key_provider() + """ + + # 1a. Create a Raw AES Keyring + raw_aes_keyring = RawAesKeyring.create_keyring() + + # 1b. Create a Raw AES Master Key Provider + raw_aes_master_key_provider = RawAesMasterKeyProvider.create_key_provider() + + # 2a. Encrypt EXAMPLE_DATA using Raw AES Keyring + ciphertext_keyring = RawAesKeyring.encrypt_using_keyring( + plaintext_data=EXAMPLE_DATA, + keyring=raw_aes_keyring + ) + + # 2b. Encrypt EXAMPLE_DATA using Raw AES Master Key Provider + ciphertext_mkp = RawAesMasterKeyProvider.encrypt_using_key_provider( + plaintext_data=EXAMPLE_DATA, + key_provider=raw_aes_master_key_provider + ) + + # Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP + # (that is ciphertext_keyring and ciphertext_mkp) are not the same because the ESDK + # generates different data keys each time for encryption of the data. But both + # ciphertexts when decrypted using keyring and MKP should give the same plaintext result. + + # 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_keyring_using_keyring = RawAesKeyring.decrypt_using_keyring( + ciphertext_data=ciphertext_keyring, + keyring=raw_aes_keyring + ) + + decrypted_ciphertext_keyring_using_mkp = RawAesMasterKeyProvider.decrypt_using_key_provider( + ciphertext_data=ciphertext_keyring, + key_provider=raw_aes_master_key_provider + ) + + assert decrypted_ciphertext_keyring_using_keyring == decrypted_ciphertext_keyring_using_mkp \ + and decrypted_ciphertext_keyring_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" + + # 4. Decrypt the ciphertext_mkp using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_mkp_using_keyring = RawAesKeyring.decrypt_using_keyring( + ciphertext_data=ciphertext_mkp, + keyring=raw_aes_keyring + ) + + decrypted_ciphertext_mkp_using_mkp = RawAesMasterKeyProvider.decrypt_using_key_provider( + ciphertext_data=ciphertext_mkp, + key_provider=raw_aes_master_key_provider + ) + + assert decrypted_ciphertext_mkp_using_keyring == decrypted_ciphertext_mkp_using_mkp \ + and decrypted_ciphertext_mkp_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" diff --git a/examples/src/migration/migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py b/examples/src/migration/migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py new file mode 100644 index 000000000..104506633 --- /dev/null +++ b/examples/src/migration/migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py @@ -0,0 +1,358 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This is a migration example for moving to the Raw RSA Keyring from Raw RSA master key provider (MKP) + +The Raw RSA keyring performs asymmetric encryption and decryption of data keys in local memory +with RSA public and private keys that you provide. In this example, we define the RSA keys to +encrypt and decrypt the data keys. + +You need to generate, store, and protect the private key, preferably in a +hardware security module (HSM) or key management system. +The encryption function encrypts the data key under the RSA public key. The decryption function +decrypts the data key using the private key. + +This example defines classes for Raw RSA Keyring and Raw RSA MKP and +then encrypts a custom input EXAMPLE_DATA with an encryption context using both +the keyring and MKP. The example then decrypts the ciphertext using both keyring and MKPs. +This example also includes some sanity checks for demonstration: +1. Decryption of these ciphertexts encrypted using keyring and MKP + is possible using both KMS keyring and KMS MKP +2. Both decrypted plaintexts are same and match EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP are not +the same because the ESDK generates different data keys each time for encryption of the data. +But both ciphertexts when decrypted using keyring and MKP should give the same plaintext result. + +For more information on how to use Raw RSA keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-rsa-keyring.html +""" + + +import aws_encryption_sdk +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme +from aws_cryptographic_materialproviders.mpl.references import IKeyring +import aws_encryption_sdk +from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm +from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey +from aws_encryption_sdk.key_providers.raw import RawMasterKeyProvider +from typing import Dict # noqa pylint: disable=wrong-import-order +import sys + +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from cryptography.hazmat.backends import default_backend as crypto_default_backend +from cryptography.hazmat.primitives import serialization as crypto_serialization +from cryptography.hazmat.primitives.asymmetric import rsa +from typing import Dict # noqa pylint: disable=wrong-import-order + +import aws_encryption_sdk +from aws_encryption_sdk import CommitmentPolicy +from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError + + +EXAMPLE_DATA: bytes = b"Hello World" + +DEFAULT_ENCRYPTION_CONTEXT : Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", +} + +DEFAULT_KEY_NAME_SPACE = "Some managed raw keys" + +DEFAULT_KEY_NAME = "My 4096-bit RSA wrapping key" + + +def generate_rsa_keys_helper(): + """Generates a 4096-bit RSA public and private key pair + + Usage: generate_rsa_keys_helper() + """ + ssh_rsa_exponent = 65537 + bit_strength = 4096 + key = rsa.generate_private_key( + backend=crypto_default_backend(), + public_exponent=ssh_rsa_exponent, + key_size=bit_strength + ) + + # This example choses a particular type of encoding, format and encryption_algorithm + # Users can choose the PublicFormat, PrivateFormat and encryption_algorithm that align most + # with their use-cases + public_key = key.public_key().public_bytes( + encoding=crypto_serialization.Encoding.PEM, + format=crypto_serialization.PublicFormat.SubjectPublicKeyInfo + ) + private_key = key.private_bytes( + encoding=crypto_serialization.Encoding.PEM, + format=crypto_serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=crypto_serialization.NoEncryption() + ) + + return public_key, private_key + + +DEFAULT_RSA_PUBLIC_KEY, DEFAULT_RSA_PRIVATE_KEY = generate_rsa_keys_helper() + + +class RawRsaKeyring(): + """Class for creating a Raw RSA Keyring and using it for encryption and decryption""" + + @staticmethod + def create_keyring(public_key, private_key): + """Demonstrate how to create a Raw RSA keyring using the key pair. + + Usage: create_keyring(public_key, private_key) + """ + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateRawRsaKeyringInput = CreateRawRsaKeyringInput( + key_namespace=DEFAULT_KEY_NAME_SPACE, + key_name=DEFAULT_KEY_NAME, + padding_scheme=PaddingScheme.OAEP_SHA256_MGF1, + public_key=public_key, + private_key=private_key + ) + + keyring: IKeyring = mat_prov.create_raw_rsa_keyring( + input=keyring_input + ) + + return keyring + + @staticmethod + def encrypt_using_keyring( + plaintext_data: bytes, + keyring: IKeyring + ): + """Demonstrate how to encrypt plaintext data using a Raw RSA keyring. + + Usage: encrypt_using_keyring(plaintext_data, keyring) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param keyring: Keyring to use for encryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + keyring=keyring, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + return ciphertext_data + + @staticmethod + def decrypt_using_keyring( + ciphertext_data: bytes, + keyring: IKeyring + ): + """Demonstrate how to decrypt ciphertext data using a Raw RSA keyring. + + Usage: decrypt_using_keyring(ciphertext_data, keyring) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param keyring: Keyring to use for decryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + keyring=keyring + ) + + return decrypted_plaintext_data + + +# This is a helper class necessary for the Raw RSA master key provider. +# In the StaticRandomMasterKeyProvider, we fix the static key to +# DEFAULT_RSA_PRIVATE_KEY in order to make the test deterministic. +# Thus, both the Raw RSA keyring and Raw RSA MKP have the same private_key +# and we are able to encrypt data using keyrings and decrypt using MKP and vice versa +# In practice, users should generate a new key pair for each key id. +class StaticRandomMasterKeyProvider(RawMasterKeyProvider): + """Randomly generates and provides 4096-bit RSA keys consistently per unique key id.""" + + # The Provider ID (or Provider) field in the JceMasterKey and RawMasterKey is + # equivalent to key namespace in the Raw keyrings + provider_id = DEFAULT_KEY_NAME_SPACE + + def __init__(self, **kwargs): # pylint: disable=unused-argument + """Initialize empty map of keys.""" + self._static_keys = {} + + def _get_raw_key(self, key_id): + """Retrieves a static, randomly generated, RSA key for the specified key id. + + :param str key_id: User-defined ID for the static key + :returns: Wrapping key that contains the specified static key + :rtype: :class:`aws_encryption_sdk.internal.crypto.WrappingKey` + """ + try: + static_key = self._static_keys[key_id] + except KeyError: + # We fix the static key in order to make the test deterministic + # In practice, you should get this key from a secure key management system such as an HSM. + static_key = DEFAULT_RSA_PRIVATE_KEY + self._static_keys[key_id] = static_key + return WrappingKey( + wrapping_algorithm=WrappingAlgorithm.RSA_OAEP_SHA256_MGF1, + wrapping_key=static_key, + wrapping_key_type=EncryptionKeyType.PRIVATE, + ) + + +class RawRsaMasterKeyProvider(): + """Class for creating a Raw RSA MKP and using it for encryption and decryption""" + + @staticmethod + def create_key_provider(): + """Demonstrate how to create a Raw RSA master key provider. + + Usage: create_key_provider() + """ + # Create a Raw RSA master key provider. + + # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name + # in the Raw keyrings + key_id = DEFAULT_KEY_NAME + + # In this example, we fix the static key to DEFAULT_RSA_PRIVATE_KEY in both the keyring + # and MKP (for MKP, we fix the static key in StaticRandomMasterKeyProvider) in order to make + # the test deterministic. Thus, both the Raw RSA keyring and Raw RSA MKP have the same + # private_key and we are able to encrypt data using keyrings and decrypt using MKP + # and vice versa. In practice, users should generate a new key pair for each key id in + # the StaticRandomMasterKeyProvider. + key_provider = StaticRandomMasterKeyProvider() + key_provider.add_master_key(key_id) + + return key_provider + + @staticmethod + def encrypt_using_key_provider( + plaintext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + ): + """Demonstrate how to encrypt plaintext data using a Raw RSA master key provider. + + Usage: encrypt_using_key_provider(plaintext_data, key_provider) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param key_provider: Master key provider to use for encryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + key_provider=key_provider, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + return ciphertext_data + + @staticmethod + def decrypt_using_key_provider( + ciphertext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + ): + """Demonstrate how to decrypt ciphertext data using a Raw RSA master key provider. + + Usage: decrypt_using_key_provider(ciphertext_data, key_provider) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param key_provider: Master key provider to use for decryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + key_provider=key_provider + ) + + return decrypted_plaintext_data + + +def migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider( + public_key=DEFAULT_RSA_PUBLIC_KEY, + private_key=DEFAULT_RSA_PRIVATE_KEY +): + """Demonstrate a migration example for moving from a Raw RSA keyring to Raw RSA MKP. + + Usage: migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider(public_key, private_key) + """ + + # 1a. Create a Raw RSA Keyring + raw_rsa_keyring = RawRsaKeyring.create_keyring(public_key=public_key, private_key=private_key) + + # 1b. Create a Raw RSA Master Key Provider + + # In this example, we fix the static key to DEFAULT_RSA_PRIVATE_KEY in both the keyring + # and MKP (for MKP, we fix the static key in StaticRandomMasterKeyProvider) in order to make + # the test deterministic. Thus, both the Raw RSA keyring and Raw RSA MKP have the same + # private_key and we are able to encrypt data using keyrings and decrypt using MKP + # and vice versa. In practice, users should generate a new key pair for each key id in + # the StaticRandomMasterKeyProvider. + raw_rsa_master_key_provider = RawRsaMasterKeyProvider.create_key_provider() + + # 2a. Encrypt EXAMPLE_DATA using Raw RSA Keyring + ciphertext_keyring = RawRsaKeyring.encrypt_using_keyring( + plaintext_data=EXAMPLE_DATA, + keyring=raw_rsa_keyring + ) + + # 2b. Encrypt EXAMPLE_DATA using Raw RSA Master Key Provider + ciphertext_mkp = RawRsaMasterKeyProvider.encrypt_using_key_provider( + plaintext_data=EXAMPLE_DATA, + key_provider=raw_rsa_master_key_provider + ) + + # Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP + # (that is ciphertext_keyring and ciphertext_mkp) are not the same because the ESDK + # generates different data keys each time for encryption of the data. But both + # ciphertexts when decrypted using keyring and MKP should give the same plaintext result. + + # 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_keyring_using_keyring = RawRsaKeyring.decrypt_using_keyring( + ciphertext_data=ciphertext_keyring, + keyring=raw_rsa_keyring + ) + + decrypted_ciphertext_keyring_using_mkp = RawRsaMasterKeyProvider.decrypt_using_key_provider( + ciphertext_data=ciphertext_keyring, + key_provider=raw_rsa_master_key_provider + ) + + assert decrypted_ciphertext_keyring_using_keyring == decrypted_ciphertext_keyring_using_mkp \ + and decrypted_ciphertext_keyring_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" + + # 4. Decrypt the ciphertext_mkp using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_mkp_using_keyring = RawRsaKeyring.decrypt_using_keyring( + ciphertext_data=ciphertext_mkp, + keyring=raw_rsa_keyring + ) + + decrypted_ciphertext_mkp_using_mkp = RawRsaMasterKeyProvider.decrypt_using_key_provider( + ciphertext_data=ciphertext_mkp, + key_provider=raw_rsa_master_key_provider + ) + + assert decrypted_ciphertext_mkp_using_keyring == decrypted_ciphertext_mkp_using_mkp \ + and decrypted_ciphertext_mkp_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" diff --git a/examples/test/migration/__init__.py b/examples/test/migration/__init__.py new file mode 100644 index 000000000..120179eda --- /dev/null +++ b/examples/test/migration/__init__.py @@ -0,0 +1,3 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Stub module indicator to make linter configuration simpler.""" diff --git a/examples/test/test_i_migration_set_commitment_policy_example.py b/examples/test/migration/test_i_migration_set_commitment_policy_example.py similarity index 83% rename from examples/test/test_i_migration_set_commitment_policy_example.py rename to examples/test/migration/test_i_migration_set_commitment_policy_example.py index afbc758bc..4620d64df 100644 --- a/examples/test/test_i_migration_set_commitment_policy_example.py +++ b/examples/test/migration/test_i_migration_set_commitment_policy_example.py @@ -3,7 +3,7 @@ """Test suite for the migration_set_commitment_policy_example.""" import pytest -from ..src.migration_set_commitment_policy_example import encrypt_and_decrypt_with_keyring +from ...src.migration.migration_set_commitment_policy_example import encrypt_and_decrypt_with_keyring pytestmark = [pytest.mark.examples] diff --git a/examples/test/migration/test_i_migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py b/examples/test/migration/test_i_migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py new file mode 100644 index 000000000..2128b0ab3 --- /dev/null +++ b/examples/test/migration/test_i_migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py @@ -0,0 +1,16 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.""" +import pytest + +from ...src.migration.migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example import ( + migration_to_aws_kms_keyring_from_aws_kms_master_key_provider, +) + +pytestmark = [pytest.mark.examples] + + +def test_migration_to_aws_kms_keyring_from_aws_kms_master_key_provider(): + """Test function for migrating to AWS KMS Keyring from AWS KMS Master Key Provider.""" + kms_key_id = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" + migration_to_aws_kms_keyring_from_aws_kms_master_key_provider(kms_key_id) diff --git a/examples/test/migration/test_i_migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py b/examples/test/migration/test_i_migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py new file mode 100644 index 000000000..12aa3e858 --- /dev/null +++ b/examples/test/migration/test_i_migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py @@ -0,0 +1,15 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.""" +import pytest + +from ...src.migration.migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example import ( + migration_to_raw_aes_keyring_from_raw_aes_master_key_provider, +) + +pytestmark = [pytest.mark.examples] + + +def test_migration_to_raw_aes_keyring_from_raw_aes_master_key_provider(): + """Test function for migrating to Raw AES Keyring from Raw AES Master Key Provider.""" + migration_to_raw_aes_keyring_from_raw_aes_master_key_provider() diff --git a/examples/test/migration/test_i_migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py b/examples/test/migration/test_i_migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py new file mode 100644 index 000000000..cafd33cf4 --- /dev/null +++ b/examples/test/migration/test_i_migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py @@ -0,0 +1,15 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.""" +import pytest + +from ...src.migration.migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example import ( + migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider, +) + +pytestmark = [pytest.mark.examples] + + +def test_migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider(): + """Test function for migrating to Raw RSA Keyring from Raw RSA Master Key Provider.""" + migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider() From 7f95db8b79336cd8d21149e4956b02d2cf56141e Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Thu, 6 Jun 2024 13:57:58 -0700 Subject: [PATCH 02/11] added README; minor fix --- examples/src/migration/README.rst | 16 ++++++++++++++++ ...from_aws_kms_master_key_provider_example.py | 1 - ...from_raw_aes_master_key_provider_example.py | 4 ++-- ...from_raw_rsa_master_key_provider_example.py | 18 +++--------------- 4 files changed, 21 insertions(+), 18 deletions(-) create mode 100644 examples/src/migration/README.rst diff --git a/examples/src/migration/README.rst b/examples/src/migration/README.rst new file mode 100644 index 000000000..44b9361b4 --- /dev/null +++ b/examples/src/migration/README.rst @@ -0,0 +1,16 @@ +################## +Migration Examples +################## + +The native Python ESDK now uses the `AWS Cryptographic Material Providers Library`_, +which introduces keyrings in place of the Master Key Provider. The MPL abstracts lower +level cryptographic materials management of encryption and decryption materials. + +This directory contains some examples to migrate from the legacy Master Key Providers +to keyrings. Here is the list of examples: +1. Migration to AWS KMS Keyring from AWS KMS Master Key Provider +2. Migration to Raw AES Keyring from Raw AES Master Key Provider +3. Migration to Raw RSA Keyring from Raw RSA Master Key Provider +4. Setting a 'CommitmentPolicy' during migration + +.. _AWS Cryptographic Material Providers Library: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/introduction.html \ No newline at end of file diff --git a/examples/src/migration/migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py b/examples/src/migration/migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py index 64f774a37..a145ac003 100644 --- a/examples/src/migration/migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py +++ b/examples/src/migration/migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py @@ -20,7 +20,6 @@ For more information on how to use KMS keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html """ - import boto3 from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig diff --git a/examples/src/migration/migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py b/examples/src/migration/migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py index 289569e05..ceb8ce4c0 100644 --- a/examples/src/migration/migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py +++ b/examples/src/migration/migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py @@ -24,6 +24,7 @@ For more information on how to use Raw AES keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html """ +import secrets from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig @@ -46,8 +47,7 @@ "the data you are handling": "is what you think it is", } -DEFAULT_AES_256_STATIC_KEY = \ - b'_\xcf"\x82\x03\x12\x9d\x00\x8a\xed\xaf\xe4\x80\x1d\x00t\xa6P\xac\xb6\xfe\xc5\xf6/{\xe7\xaaO\x01\x13W\x85' +DEFAULT_AES_256_STATIC_KEY = secrets.token_bytes(32) DEFAULT_KEY_NAME_SPACE = "Some managed raw keys" diff --git a/examples/src/migration/migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py b/examples/src/migration/migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py index 104506633..5c1787f06 100644 --- a/examples/src/migration/migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py +++ b/examples/src/migration/migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py @@ -28,20 +28,6 @@ For more information on how to use Raw RSA keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-rsa-keyring.html """ - - -import aws_encryption_sdk -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme -from aws_cryptographic_materialproviders.mpl.references import IKeyring -import aws_encryption_sdk -from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm -from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey -from aws_encryption_sdk.key_providers.raw import RawMasterKeyProvider -from typing import Dict # noqa pylint: disable=wrong-import-order -import sys - from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig from aws_cryptographic_materialproviders.mpl.models import CreateRawRsaKeyringInput, PaddingScheme @@ -54,7 +40,9 @@ import aws_encryption_sdk from aws_encryption_sdk import CommitmentPolicy from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError - +from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm +from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey +from aws_encryption_sdk.key_providers.raw import RawMasterKeyProvider EXAMPLE_DATA: bytes = b"Hello World" From b69c4187bfc0cdbdab2563365763a175cb3ebd34 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Thu, 6 Jun 2024 14:08:12 -0700 Subject: [PATCH 03/11] fix flake8 --- ...aws_kms_keyring_from_aws_kms_master_key_provider_example.py | 1 - ...raw_aes_keyring_from_raw_aes_master_key_provider_example.py | 1 - ...raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py | 3 --- 3 files changed, 5 deletions(-) diff --git a/examples/src/migration/migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py b/examples/src/migration/migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py index a145ac003..1afee749f 100644 --- a/examples/src/migration/migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py +++ b/examples/src/migration/migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py @@ -216,7 +216,6 @@ def migration_to_aws_kms_keyring_from_aws_kms_master_key_provider( For more information on KMS Key identifiers, see https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id """ - # 1a. Create a AWS KMS Keyring aws_kms_keyring = AwsKmsKeyring.create_keyring(kms_key_id=kms_key_id) diff --git a/examples/src/migration/migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py b/examples/src/migration/migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py index ceb8ce4c0..4a6fed030 100644 --- a/examples/src/migration/migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py +++ b/examples/src/migration/migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py @@ -231,7 +231,6 @@ def migration_to_raw_aes_keyring_from_raw_aes_master_key_provider(): Usage: migration_to_raw_aes_keyring_from_raw_aes_master_key_provider() """ - # 1a. Create a Raw AES Keyring raw_aes_keyring = RawAesKeyring.create_keyring() diff --git a/examples/src/migration/migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py b/examples/src/migration/migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py index 5c1787f06..734cdf075 100644 --- a/examples/src/migration/migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py +++ b/examples/src/migration/migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py @@ -38,8 +38,6 @@ from typing import Dict # noqa pylint: disable=wrong-import-order import aws_encryption_sdk -from aws_encryption_sdk import CommitmentPolicy -from aws_encryption_sdk.exceptions import AWSEncryptionSDKClientError from aws_encryption_sdk.identifiers import EncryptionKeyType, WrappingAlgorithm from aws_encryption_sdk.internal.crypto.wrapping_keys import WrappingKey from aws_encryption_sdk.key_providers.raw import RawMasterKeyProvider @@ -282,7 +280,6 @@ def migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider( Usage: migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider(public_key, private_key) """ - # 1a. Create a Raw RSA Keyring raw_rsa_keyring = RawRsaKeyring.create_keyring(public_key=public_key, private_key=private_key) From 13acd284e38a37d97fb73a0fd6016868781bccda Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Thu, 6 Jun 2024 17:00:32 -0700 Subject: [PATCH 04/11] refactoring --- examples/src/migration/README.rst | 14 +- .../migration_aws_kms_key_example.py | 276 ++++++++++++++++++ ...le.py => migration_raw_aes_key_example.py} | 0 ...le.py => migration_raw_rsa_key_example.py} | 0 ...rom_aws_kms_master_key_provider_example.py | 272 ----------------- .../test_i_migration_aws_kms_key_example.py | 16 + ...> test_i_migration_raw_aes_key_example.py} | 2 +- ...> test_i_migration_raw_rsa_key_example.py} | 0 ...rom_aws_kms_master_key_provider_example.py | 16 - 9 files changed, 301 insertions(+), 295 deletions(-) create mode 100644 examples/src/migration/migration_aws_kms_key_example.py rename examples/src/migration/{migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py => migration_raw_aes_key_example.py} (100%) rename examples/src/migration/{migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py => migration_raw_rsa_key_example.py} (100%) delete mode 100644 examples/src/migration/migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py create mode 100644 examples/test/migration/test_i_migration_aws_kms_key_example.py rename examples/test/migration/{test_i_migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py => test_i_migration_raw_aes_key_example.py} (84%) rename examples/test/migration/{test_i_migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py => test_i_migration_raw_rsa_key_example.py} (100%) delete mode 100644 examples/test/migration/test_i_migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py diff --git a/examples/src/migration/README.rst b/examples/src/migration/README.rst index 44b9361b4..a709523e9 100644 --- a/examples/src/migration/README.rst +++ b/examples/src/migration/README.rst @@ -3,14 +3,16 @@ Migration Examples ################## The native Python ESDK now uses the `AWS Cryptographic Material Providers Library`_, -which introduces keyrings in place of the Master Key Provider. The MPL abstracts lower +which introduces keyrings in place of Master Key Providers. The MPL abstracts lower level cryptographic materials management of encryption and decryption materials. -This directory contains some examples to migrate from the legacy Master Key Providers -to keyrings. Here is the list of examples: -1. Migration to AWS KMS Keyring from AWS KMS Master Key Provider -2. Migration to Raw AES Keyring from Raw AES Master Key Provider -3. Migration to Raw RSA Keyring from Raw RSA Master Key Provider +This directory contains some examples to migrate from the old version of the ESDK. +If you have messages encrypted in the older versions using Master Key Providers, +these examples can guide you on how to decrypt those messages using the new version +of the ESDK. Here is the list of examples: +1. Migration example for AWS KMS keys +2. Migration example for Raw AES keys +3. Migration example for Raw RSA keys 4. Setting a 'CommitmentPolicy' during migration .. _AWS Cryptographic Material Providers Library: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/introduction.html \ No newline at end of file diff --git a/examples/src/migration/migration_aws_kms_key_example.py b/examples/src/migration/migration_aws_kms_key_example.py new file mode 100644 index 000000000..b2912ba1f --- /dev/null +++ b/examples/src/migration/migration_aws_kms_key_example.py @@ -0,0 +1,276 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +""" +This is a migration example for moving to the AWS KMS Keyring from AWS KMS master key provider (MKP) + +The AWS KMS keyring uses symmetric encryption KMS keys to generate, encrypt and +decrypt data keys. This example creates the KMS Keyring and KMS MKP and +then encrypts a custom input EXAMPLE_DATA with an encryption context using both +the keyring and MKP. The example then decrypts the ciphertext using both keyring and MKPs. +This example also includes some sanity checks for demonstration: +1. Decryption of these ciphertexts encrypted using keyring and MKP + is possible using both KMS keyring and KMS MKP +2. Both decrypted plaintexts are same and match EXAMPLE_DATA +These sanity checks are for demonstration in the example only. You do not need these in your code. + +Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP are not +the same because the ESDK generates different data keys each time for encryption of the data. +But both ciphertexts when decrypted using keyring and MKP should give the same plaintext result. + +For more information on how to use KMS keyrings, see +https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html +""" +import boto3 +from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders +from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig +from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput +from aws_cryptographic_materialproviders.mpl.references import IKeyring +from typing import Dict # noqa pylint: disable=wrong-import-order + +import aws_encryption_sdk + +EXAMPLE_DATA: bytes = b"Hello World" + +DEFAULT_ENCRYPTION_CONTEXT : Dict[str, str] = { + "encryption": "context", + "is not": "secret", + "but adds": "useful metadata", + "that can help you": "be confident that", + "the data you are handling": "is what you think it is", +} + + +def create_kms_client(aws_region="us-west-2"): + """Create an AWS KMS client. + + Usage: create_kms_client(aws_region) + :param aws_region: AWS region to use for KMS client. + :type aws_region: string + """ + # Create a boto3 client for KMS. + kms_client = boto3.client('kms', region_name=aws_region) + + return kms_client + + +def create_keyring( + kms_key_id: str +): + """Demonstrate how to create an AWS KMS keyring. + + Usage: create_keyring(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # Create a boto3 client for KMS. + kms_client = create_kms_client() + + # Create a KMS keyring + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) + + keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( + kms_key_id=kms_key_id, + kms_client=kms_client + ) + + keyring: IKeyring = mat_prov.create_aws_kms_keyring( + input=keyring_input + ) + + return keyring + + +def encrypt_using_keyring( + plaintext_data: bytes, + keyring: IKeyring, + client: aws_encryption_sdk.EncryptionSDKClient +): + """Demonstrate how to encrypt plaintext data using an AWS KMS keyring. + + Usage: encrypt_using_keyring(plaintext_data, keyring) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param keyring: Keyring to use for encryption. + :type keyring: IKeyring + :param client: AWS Encryption SDK client. + :type client: aws_encryption_sdk.EncryptionSDKClient + """ + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + keyring=keyring, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + return ciphertext_data + + +def decrypt_using_keyring( + ciphertext_data: bytes, + keyring: IKeyring, + client: aws_encryption_sdk.EncryptionSDKClient +): + """Demonstrate how to decrypt ciphertext data using an AWS KMS keyring. + + Usage: decrypt_using_keyring(ciphertext_data, keyring) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param keyring: Keyring to use for decryption. + :type keyring: IKeyring + :param client: AWS Encryption SDK client. + :type client: aws_encryption_sdk.EncryptionSDKClient + """ + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + keyring=keyring + ) + + return decrypted_plaintext_data + + +def create_key_provider( + kms_key_id: str +): + """Demonstrate how to create an AWS KMS master key provider. + + Usage: create_key_provider(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + # Create a KMS master key provider. + key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[ + kms_key_id, + ]) + + return key_provider + + +def encrypt_using_key_provider( + plaintext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider, + client: aws_encryption_sdk.EncryptionSDKClient +): + """Demonstrate how to encrypt plaintext data using an AWS KMS master key provider. + + Usage: encrypt_using_key_provider(plaintext_data, key_provider) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param key_provider: Master key provider to use for encryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + :param client: AWS Encryption SDK client. + :type client: aws_encryption_sdk.EncryptionSDKClient + """ + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + key_provider=key_provider, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + return ciphertext_data + + +def decrypt_using_key_provider( + ciphertext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider, + client: aws_encryption_sdk.EncryptionSDKClient +): + """Demonstrate how to decrypt ciphertext data using an AWS KMS master key provider. + + Usage: decrypt_using_key_provider(ciphertext_data, key_provider) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param key_provider: Master key provider to use for decryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + :param client: AWS Encryption SDK client. + :type client: aws_encryption_sdk.EncryptionSDKClient + """ + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + key_provider=key_provider + ) + + return decrypted_plaintext_data + + +def migration_aws_kms_key( + kms_key_id: str +): + """Demonstrate a migration example for moving from an AWS KMS keyring to AWS KMS MKP. + + Usage: migration_to_aws_kms_keyring_from_aws_kms_master_key_provider(kms_key_id) + :param kms_key_id: KMS Key identifier for the KMS key you want to use for encryption and + decryption of your data keys. + :type kms_key_id: string + + For more information on KMS Key identifiers, see + https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + # 1a. Create a AWS KMS Keyring + aws_kms_keyring = create_keyring(kms_key_id=kms_key_id) + + # 1b. Create a AWS KMS Master Key Provider + aws_kms_master_key_provider = create_key_provider(kms_key_id=kms_key_id) + + # 2a. Encrypt EXAMPLE_DATA using AWS KMS Keyring + ciphertext_keyring = encrypt_using_keyring( + plaintext_data=EXAMPLE_DATA, + keyring=aws_kms_keyring, + client=client + ) + + # 2b. Encrypt EXAMPLE_DATA using AWS KMS Master Key Provider + ciphertext_mkp = encrypt_using_key_provider( + plaintext_data=EXAMPLE_DATA, + key_provider=aws_kms_master_key_provider, + client=client + ) + + # Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP + # (that is ciphertext_keyring and ciphertext_mkp) are not the same because the ESDK + # generates different data keys each time for encryption of the data. But both + # ciphertexts when decrypted using keyring and MKP should give the same plaintext result. + + # 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_keyring_using_keyring = decrypt_using_keyring( + ciphertext_data=ciphertext_keyring, + keyring=aws_kms_keyring, + client=client + ) + + decrypted_ciphertext_keyring_using_mkp = decrypt_using_key_provider( + ciphertext_data=ciphertext_keyring, + key_provider=aws_kms_master_key_provider, + client=client + ) + + assert decrypted_ciphertext_keyring_using_keyring == decrypted_ciphertext_keyring_using_mkp \ + and decrypted_ciphertext_keyring_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" + + # 4. Decrypt the ciphertext_mkp using both the keyring and MKP and ensure the + # resulting plaintext is the same and also equal to EXAMPLE_DATA + decrypted_ciphertext_mkp_using_keyring = decrypt_using_keyring( + ciphertext_data=ciphertext_mkp, + keyring=aws_kms_keyring, + client=client + ) + + decrypted_ciphertext_mkp_using_mkp = decrypt_using_key_provider( + ciphertext_data=ciphertext_mkp, + key_provider=aws_kms_master_key_provider, + client=client + ) + + assert decrypted_ciphertext_mkp_using_keyring == decrypted_ciphertext_mkp_using_mkp \ + and decrypted_ciphertext_mkp_using_keyring == EXAMPLE_DATA, \ + "Decrypted outputs using keyring and master key provider are not the same" diff --git a/examples/src/migration/migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py b/examples/src/migration/migration_raw_aes_key_example.py similarity index 100% rename from examples/src/migration/migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py rename to examples/src/migration/migration_raw_aes_key_example.py diff --git a/examples/src/migration/migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py b/examples/src/migration/migration_raw_rsa_key_example.py similarity index 100% rename from examples/src/migration/migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py rename to examples/src/migration/migration_raw_rsa_key_example.py diff --git a/examples/src/migration/migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py b/examples/src/migration/migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py deleted file mode 100644 index 1afee749f..000000000 --- a/examples/src/migration/migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py +++ /dev/null @@ -1,272 +0,0 @@ -# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0 -""" -This is a migration example for moving to the AWS KMS Keyring from AWS KMS master key provider (MKP) - -The AWS KMS keyring uses symmetric encryption KMS keys to generate, encrypt and -decrypt data keys. This example defines classes for KMS Keyring and KMS MKP and -then encrypts a custom input EXAMPLE_DATA with an encryption context using both -the keyring and MKP. The example then decrypts the ciphertext using both keyring and MKPs. -This example also includes some sanity checks for demonstration: -1. Decryption of these ciphertexts encrypted using keyring and MKP - is possible using both KMS keyring and KMS MKP -2. Both decrypted plaintexts are same and match EXAMPLE_DATA -These sanity checks are for demonstration in the example only. You do not need these in your code. - -Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP are not -the same because the ESDK generates different data keys each time for encryption of the data. -But both ciphertexts when decrypted using keyring and MKP should give the same plaintext result. - -For more information on how to use KMS keyrings, see -https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html -""" -import boto3 -from aws_cryptographic_materialproviders.mpl import AwsCryptographicMaterialProviders -from aws_cryptographic_materialproviders.mpl.config import MaterialProvidersConfig -from aws_cryptographic_materialproviders.mpl.models import CreateAwsKmsKeyringInput -from aws_cryptographic_materialproviders.mpl.references import IKeyring -from typing import Dict # noqa pylint: disable=wrong-import-order - -import aws_encryption_sdk - -EXAMPLE_DATA: bytes = b"Hello World" - -DEFAULT_ENCRYPTION_CONTEXT : Dict[str, str] = { - "encryption": "context", - "is not": "secret", - "but adds": "useful metadata", - "that can help you": "be confident that", - "the data you are handling": "is what you think it is", -} - - -class AwsKmsKeyring(): - """Class for creating a KMS Keyring and using it for encryption and decryption""" - - @staticmethod - def create_kms_client(aws_region="us-west-2"): - """Create an AWS KMS client. - - Usage: create_kms_client(aws_region) - :param aws_region: AWS region to use for KMS client. - :type aws_region: string - """ - # Create a boto3 client for KMS. - kms_client = boto3.client('kms', region_name=aws_region) - - return kms_client - - @staticmethod - def create_keyring( - kms_key_id: str - ): - """Demonstrate how to create an AWS KMS keyring. - - Usage: create_keyring(kms_key_id) - :param kms_key_id: KMS Key identifier for the KMS key you want to use. - :type kms_key_id: string - - For more information on KMS Key identifiers, see - https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id - """ - # Create a boto3 client for KMS. - kms_client = AwsKmsKeyring.create_kms_client() - - # Create a KMS keyring - mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( - config=MaterialProvidersConfig() - ) - - keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput( - kms_key_id=kms_key_id, - kms_client=kms_client - ) - - keyring: IKeyring = mat_prov.create_aws_kms_keyring( - input=keyring_input - ) - - return keyring - - @staticmethod - def encrypt_using_keyring( - plaintext_data: bytes, - keyring: IKeyring - ): - """Demonstrate how to encrypt plaintext data using an AWS KMS keyring. - - Usage: encrypt_using_keyring(plaintext_data, keyring) - :param plaintext_data: plaintext data you want to encrypt - :type: bytes - :param keyring: Keyring to use for encryption. - :type keyring: IKeyring - """ - client = aws_encryption_sdk.EncryptionSDKClient() - - ciphertext_data, _ = client.encrypt( - source=plaintext_data, - keyring=keyring, - encryption_context=DEFAULT_ENCRYPTION_CONTEXT - ) - - return ciphertext_data - - @staticmethod - def decrypt_using_keyring( - ciphertext_data: bytes, - keyring: IKeyring - ): - """Demonstrate how to decrypt ciphertext data using an AWS KMS keyring. - - Usage: decrypt_using_keyring(ciphertext_data, keyring) - :param ciphertext_data: ciphertext data you want to decrypt - :type: bytes - :param keyring: Keyring to use for decryption. - :type keyring: IKeyring - """ - client = aws_encryption_sdk.EncryptionSDKClient() - - decrypted_plaintext_data, _ = client.decrypt( - source=ciphertext_data, - keyring=keyring - ) - - return decrypted_plaintext_data - - -class AwsKmsMasterKeyProvider(): - """Class for creating a KMS MKP and using it for encryption and decryption""" - - @staticmethod - def create_key_provider( - kms_key_id: str - ): - """Demonstrate how to create an AWS KMS master key provider. - - Usage: create_key_provider(kms_key_id) - :param kms_key_id: KMS Key identifier for the KMS key you want to use. - :type kms_key_id: string - - For more information on KMS Key identifiers, see - https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id - """ - # Create a KMS master key provider. - key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[ - kms_key_id, - ]) - - return key_provider - - @staticmethod - def encrypt_using_key_provider( - plaintext_data: bytes, - key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - ): - """Demonstrate how to encrypt plaintext data using an AWS KMS master key provider. - - Usage: encrypt_using_key_provider(plaintext_data, key_provider) - :param plaintext_data: plaintext data you want to encrypt - :type: bytes - :param key_provider: Master key provider to use for encryption. - :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - """ - client = aws_encryption_sdk.EncryptionSDKClient() - - ciphertext_data, _ = client.encrypt( - source=plaintext_data, - key_provider=key_provider, - encryption_context=DEFAULT_ENCRYPTION_CONTEXT - ) - - return ciphertext_data - - @staticmethod - def decrypt_using_key_provider( - ciphertext_data: bytes, - key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - ): - """Demonstrate how to decrypt ciphertext data using an AWS KMS master key provider. - - Usage: decrypt_using_key_provider(ciphertext_data, key_provider) - :param ciphertext_data: ciphertext data you want to decrypt - :type: bytes - :param key_provider: Master key provider to use for decryption. - :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - """ - client = aws_encryption_sdk.EncryptionSDKClient() - - decrypted_plaintext_data, _ = client.decrypt( - source=ciphertext_data, - key_provider=key_provider - ) - - return decrypted_plaintext_data - - -def migration_to_aws_kms_keyring_from_aws_kms_master_key_provider( - kms_key_id: str -): - """Demonstrate a migration example for moving from an AWS KMS keyring to AWS KMS MKP. - - Usage: migration_to_aws_kms_keyring_from_aws_kms_master_key_provider(kms_key_id) - :param kms_key_id: KMS Key identifier for the KMS key you want to use for encryption and - decryption of your data keys. - :type kms_key_id: string - - For more information on KMS Key identifiers, see - https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id - """ - # 1a. Create a AWS KMS Keyring - aws_kms_keyring = AwsKmsKeyring.create_keyring(kms_key_id=kms_key_id) - - # 1b. Create a AWS KMS Master Key Provider - aws_kms_master_key_provider = AwsKmsMasterKeyProvider.create_key_provider(kms_key_id=kms_key_id) - - # 2a. Encrypt EXAMPLE_DATA using AWS KMS Keyring - ciphertext_keyring = AwsKmsKeyring.encrypt_using_keyring( - plaintext_data=EXAMPLE_DATA, - keyring=aws_kms_keyring - ) - - # 2b. Encrypt EXAMPLE_DATA using AWS KMS Master Key Provider - ciphertext_mkp = AwsKmsMasterKeyProvider.encrypt_using_key_provider( - plaintext_data=EXAMPLE_DATA, - key_provider=aws_kms_master_key_provider - ) - - # Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP - # (that is ciphertext_keyring and ciphertext_mkp) are not the same because the ESDK - # generates different data keys each time for encryption of the data. But both - # ciphertexts when decrypted using keyring and MKP should give the same plaintext result. - - # 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the - # resulting plaintext is the same and also equal to EXAMPLE_DATA - decrypted_ciphertext_keyring_using_keyring = AwsKmsKeyring.decrypt_using_keyring( - ciphertext_data=ciphertext_keyring, - keyring=aws_kms_keyring - ) - - decrypted_ciphertext_keyring_using_mkp = AwsKmsMasterKeyProvider.decrypt_using_key_provider( - ciphertext_data=ciphertext_keyring, - key_provider=aws_kms_master_key_provider - ) - - assert decrypted_ciphertext_keyring_using_keyring == decrypted_ciphertext_keyring_using_mkp \ - and decrypted_ciphertext_keyring_using_keyring == EXAMPLE_DATA, \ - "Decrypted outputs using keyring and master key provider are not the same" - - # 4. Decrypt the ciphertext_mkp using both the keyring and MKP and ensure the - # resulting plaintext is the same and also equal to EXAMPLE_DATA - decrypted_ciphertext_mkp_using_keyring = AwsKmsKeyring.decrypt_using_keyring( - ciphertext_data=ciphertext_mkp, - keyring=aws_kms_keyring - ) - - decrypted_ciphertext_mkp_using_mkp = AwsKmsMasterKeyProvider.decrypt_using_key_provider( - ciphertext_data=ciphertext_mkp, - key_provider=aws_kms_master_key_provider - ) - - assert decrypted_ciphertext_mkp_using_keyring == decrypted_ciphertext_mkp_using_mkp \ - and decrypted_ciphertext_mkp_using_keyring == EXAMPLE_DATA, \ - "Decrypted outputs using keyring and master key provider are not the same" diff --git a/examples/test/migration/test_i_migration_aws_kms_key_example.py b/examples/test/migration/test_i_migration_aws_kms_key_example.py new file mode 100644 index 000000000..56202ad71 --- /dev/null +++ b/examples/test/migration/test_i_migration_aws_kms_key_example.py @@ -0,0 +1,16 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Test suite for the migration_aws_kms_key_example.""" +import pytest + +from ...src.migration.migration_aws_kms_key_example import ( + migration_aws_kms_key, +) + +pytestmark = [pytest.mark.examples] + + +def test_migration_aws_kms_key(): + """Test function for migrating using AWS KMS Keys.""" + kms_key_id = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" + migration_aws_kms_key(kms_key_id) diff --git a/examples/test/migration/test_i_migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py b/examples/test/migration/test_i_migration_raw_aes_key_example.py similarity index 84% rename from examples/test/migration/test_i_migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py rename to examples/test/migration/test_i_migration_raw_aes_key_example.py index 12aa3e858..d068b2231 100644 --- a/examples/test/migration/test_i_migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.py +++ b/examples/test/migration/test_i_migration_raw_aes_key_example.py @@ -3,7 +3,7 @@ """Test suite for the migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.""" import pytest -from ...src.migration.migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example import ( +from ...src.migration.migration_raw_aes_key_example import ( migration_to_raw_aes_keyring_from_raw_aes_master_key_provider, ) diff --git a/examples/test/migration/test_i_migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py b/examples/test/migration/test_i_migration_raw_rsa_key_example.py similarity index 100% rename from examples/test/migration/test_i_migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.py rename to examples/test/migration/test_i_migration_raw_rsa_key_example.py diff --git a/examples/test/migration/test_i_migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py b/examples/test/migration/test_i_migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py deleted file mode 100644 index 2128b0ab3..000000000 --- a/examples/test/migration/test_i_migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0 -"""Test suite for the migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example.""" -import pytest - -from ...src.migration.migration_to_aws_kms_keyring_from_aws_kms_master_key_provider_example import ( - migration_to_aws_kms_keyring_from_aws_kms_master_key_provider, -) - -pytestmark = [pytest.mark.examples] - - -def test_migration_to_aws_kms_keyring_from_aws_kms_master_key_provider(): - """Test function for migrating to AWS KMS Keyring from AWS KMS Master Key Provider.""" - kms_key_id = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" - migration_to_aws_kms_keyring_from_aws_kms_master_key_provider(kms_key_id) From a528e2d84b7e9d8152250cccfca0874028d680c5 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Thu, 6 Jun 2024 17:02:28 -0700 Subject: [PATCH 05/11] fix --- examples/test/migration/test_i_migration_raw_rsa_key_example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/test/migration/test_i_migration_raw_rsa_key_example.py b/examples/test/migration/test_i_migration_raw_rsa_key_example.py index cafd33cf4..cfe3c3b2a 100644 --- a/examples/test/migration/test_i_migration_raw_rsa_key_example.py +++ b/examples/test/migration/test_i_migration_raw_rsa_key_example.py @@ -3,7 +3,7 @@ """Test suite for the migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.""" import pytest -from ...src.migration.migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example import ( +from ...src.migration.migration_raw_rsa_key_example import ( migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider, ) From 1ba28ef2166c1adc5b9dac06bb8dceb484201340 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Fri, 7 Jun 2024 11:07:16 -0700 Subject: [PATCH 06/11] removed classes for keyrings / mkps --- .../migration_aws_kms_key_example.py | 6 +- .../migration_raw_aes_key_example.py | 242 ++++++++--------- .../migration_raw_rsa_key_example.py | 256 +++++++++--------- .../test_i_migration_raw_aes_key_example.py | 6 +- .../test_i_migration_raw_rsa_key_example.py | 6 +- 5 files changed, 250 insertions(+), 266 deletions(-) diff --git a/examples/src/migration/migration_aws_kms_key_example.py b/examples/src/migration/migration_aws_kms_key_example.py index b2912ba1f..9b5efc035 100644 --- a/examples/src/migration/migration_aws_kms_key_example.py +++ b/examples/src/migration/migration_aws_kms_key_example.py @@ -4,7 +4,7 @@ This is a migration example for moving to the AWS KMS Keyring from AWS KMS master key provider (MKP) The AWS KMS keyring uses symmetric encryption KMS keys to generate, encrypt and -decrypt data keys. This example creates the KMS Keyring and KMS MKP and +decrypt data keys. This example creates a KMS Keyring and KMS MKP and then encrypts a custom input EXAMPLE_DATA with an encryption context using both the keyring and MKP. The example then decrypts the ciphertext using both keyring and MKPs. This example also includes some sanity checks for demonstration: @@ -202,9 +202,9 @@ def decrypt_using_key_provider( def migration_aws_kms_key( kms_key_id: str ): - """Demonstrate a migration example for moving from an AWS KMS keyring to AWS KMS MKP. + """Demonstrate a migration example for moving to an AWS KMS keyring from AWS KMS MKP. - Usage: migration_to_aws_kms_keyring_from_aws_kms_master_key_provider(kms_key_id) + Usage: migration_aws_kms_key(kms_key_id) :param kms_key_id: KMS Key identifier for the KMS key you want to use for encryption and decryption of your data keys. :type kms_key_id: string diff --git a/examples/src/migration/migration_raw_aes_key_example.py b/examples/src/migration/migration_raw_aes_key_example.py index 4a6fed030..3a30ad9a3 100644 --- a/examples/src/migration/migration_raw_aes_key_example.py +++ b/examples/src/migration/migration_raw_aes_key_example.py @@ -8,7 +8,7 @@ preferably in a hardware security module (HSM) or key management system. Use a Raw AES keyring when you need to provide the wrapping key and encrypt the data keys locally or offline. -This example defines classes for Raw AES Keyring and Raw AES MKP and +This example creates a Raw AES Keyring and Raw AES MKP and then encrypts a custom input EXAMPLE_DATA with an encryption context using both the keyring and MKP. The example then decrypts the ciphertext using both keyring and MKPs. This example also includes some sanity checks for demonstration: @@ -54,79 +54,75 @@ DEFAULT_KEY_NAME = "My 256-bit AES wrapping key" -class RawAesKeyring(): - """Class for creating a Raw AES Keyring and using it for encryption and decryption""" +def create_keyring(): + """Demonstrate how to create a Raw AES keyring. - @staticmethod - def create_keyring(): - """Demonstrate how to create a Raw AES keyring. + Usage: create_keyring() + """ + # We fix the static key in order to make the test deterministic + static_key = DEFAULT_AES_256_STATIC_KEY - Usage: create_keyring() - """ - # We fix the static key in order to make the test deterministic - static_key = DEFAULT_AES_256_STATIC_KEY + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) - mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( - config=MaterialProvidersConfig() - ) + keyring_input: CreateRawAesKeyringInput = CreateRawAesKeyringInput( + key_namespace=DEFAULT_KEY_NAME_SPACE, + key_name=DEFAULT_KEY_NAME, + wrapping_key=static_key, + wrapping_alg=AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16 + ) - keyring_input: CreateRawAesKeyringInput = CreateRawAesKeyringInput( - key_namespace=DEFAULT_KEY_NAME_SPACE, - key_name=DEFAULT_KEY_NAME, - wrapping_key=static_key, - wrapping_alg=AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16 - ) + keyring: IKeyring = mat_prov.create_raw_aes_keyring( + input=keyring_input + ) - keyring: IKeyring = mat_prov.create_raw_aes_keyring( - input=keyring_input - ) + return keyring - return keyring - @staticmethod - def encrypt_using_keyring( - plaintext_data: bytes, - keyring: IKeyring - ): - """Demonstrate how to encrypt plaintext data using a Raw AES keyring. +def encrypt_using_keyring( + plaintext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to encrypt plaintext data using a Raw AES keyring. - Usage: encrypt_using_keyring(plaintext_data, keyring) - :param plaintext_data: plaintext data you want to encrypt - :type: bytes - :param keyring: Keyring to use for encryption. - :type keyring: IKeyring - """ - client = aws_encryption_sdk.EncryptionSDKClient() + Usage: encrypt_using_keyring(plaintext_data, keyring) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param keyring: Keyring to use for encryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() - ciphertext_data, _ = client.encrypt( - source=plaintext_data, - keyring=keyring, - encryption_context=DEFAULT_ENCRYPTION_CONTEXT - ) + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + keyring=keyring, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) - return ciphertext_data + return ciphertext_data - @staticmethod - def decrypt_using_keyring( - ciphertext_data: bytes, - keyring: IKeyring - ): - """Demonstrate how to decrypt ciphertext data using a Raw AES keyring. - Usage: decrypt_using_keyring(ciphertext_data, keyring) - :param ciphertext_data: ciphertext data you want to decrypt - :type: bytes - :param keyring: Keyring to use for decryption. - :type keyring: IKeyring - """ - client = aws_encryption_sdk.EncryptionSDKClient() +def decrypt_using_keyring( + ciphertext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to decrypt ciphertext data using a Raw AES keyring. - decrypted_plaintext_data, _ = client.decrypt( - source=ciphertext_data, - keyring=keyring - ) + Usage: decrypt_using_keyring(ciphertext_data, keyring) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param keyring: Keyring to use for decryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() - return decrypted_plaintext_data + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + keyring=keyring + ) + + return decrypted_plaintext_data # This is a helper class necessary for the Raw AES master key provider @@ -162,89 +158,85 @@ def _get_raw_key(self, key_id): ) -class RawAesMasterKeyProvider(): - """Class for creating a Raw AES MKP and using it for encryption and decryption""" +def create_key_provider(): + """Demonstrate how to create a Raw AES master key provider. - @staticmethod - def create_key_provider(): - """Demonstrate how to create a Raw AES master key provider. + Usage: create_key_provider() + """ + # Create a Raw AES master key provider. - Usage: create_key_provider() - """ - # Create a Raw AES master key provider. - - # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name in the Raw keyrings - key_id = DEFAULT_KEY_NAME - key_provider = StaticRandomMasterKeyProvider() - key_provider.add_master_key(key_id) - - return key_provider - - @staticmethod - def encrypt_using_key_provider( - plaintext_data: bytes, - key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - ): - """Demonstrate how to encrypt plaintext data using a Raw AES master key provider. - - Usage: encrypt_using_key_provider(plaintext_data, key_provider) - :param plaintext_data: plaintext data you want to encrypt - :type: bytes - :param key_provider: Master key provider to use for encryption. - :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - """ - client = aws_encryption_sdk.EncryptionSDKClient() + # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name in the Raw keyrings + key_id = DEFAULT_KEY_NAME + key_provider = StaticRandomMasterKeyProvider() + key_provider.add_master_key(key_id) - ciphertext_data, _ = client.encrypt( - source=plaintext_data, - key_provider=key_provider, - encryption_context=DEFAULT_ENCRYPTION_CONTEXT - ) + return key_provider - return ciphertext_data - @staticmethod - def decrypt_using_key_provider( - ciphertext_data: bytes, - key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - ): - """Demonstrate how to decrypt ciphertext data using a Raw AES master key provider. +def encrypt_using_key_provider( + plaintext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider +): + """Demonstrate how to encrypt plaintext data using a Raw AES master key provider. - Usage: decrypt_using_key_provider(ciphertext_data, key_provider) - :param ciphertext_data: ciphertext data you want to decrypt - :type: bytes - :param key_provider: Master key provider to use for decryption. - :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - """ - client = aws_encryption_sdk.EncryptionSDKClient() + Usage: encrypt_using_key_provider(plaintext_data, key_provider) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param key_provider: Master key provider to use for encryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() - decrypted_plaintext_data, _ = client.decrypt( - source=ciphertext_data, - key_provider=key_provider - ) + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + key_provider=key_provider, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + return ciphertext_data + + +def decrypt_using_key_provider( + ciphertext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider +): + """Demonstrate how to decrypt ciphertext data using a Raw AES master key provider. + + Usage: decrypt_using_key_provider(ciphertext_data, key_provider) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param key_provider: Master key provider to use for decryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + key_provider=key_provider + ) - return decrypted_plaintext_data + return decrypted_plaintext_data -def migration_to_raw_aes_keyring_from_raw_aes_master_key_provider(): - """Demonstrate a migration example for moving from a Raw AES keyring to Raw AES MKP. +def migration_raw_aes_key(): + """Demonstrate a migration example for moving to a Raw AES keyring from Raw AES MKP. - Usage: migration_to_raw_aes_keyring_from_raw_aes_master_key_provider() + Usage: migration_raw_aes_key() """ # 1a. Create a Raw AES Keyring - raw_aes_keyring = RawAesKeyring.create_keyring() + raw_aes_keyring = create_keyring() # 1b. Create a Raw AES Master Key Provider - raw_aes_master_key_provider = RawAesMasterKeyProvider.create_key_provider() + raw_aes_master_key_provider = create_key_provider() # 2a. Encrypt EXAMPLE_DATA using Raw AES Keyring - ciphertext_keyring = RawAesKeyring.encrypt_using_keyring( + ciphertext_keyring = encrypt_using_keyring( plaintext_data=EXAMPLE_DATA, keyring=raw_aes_keyring ) # 2b. Encrypt EXAMPLE_DATA using Raw AES Master Key Provider - ciphertext_mkp = RawAesMasterKeyProvider.encrypt_using_key_provider( + ciphertext_mkp = encrypt_using_key_provider( plaintext_data=EXAMPLE_DATA, key_provider=raw_aes_master_key_provider ) @@ -256,12 +248,12 @@ def migration_to_raw_aes_keyring_from_raw_aes_master_key_provider(): # 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the # resulting plaintext is the same and also equal to EXAMPLE_DATA - decrypted_ciphertext_keyring_using_keyring = RawAesKeyring.decrypt_using_keyring( + decrypted_ciphertext_keyring_using_keyring = decrypt_using_keyring( ciphertext_data=ciphertext_keyring, keyring=raw_aes_keyring ) - decrypted_ciphertext_keyring_using_mkp = RawAesMasterKeyProvider.decrypt_using_key_provider( + decrypted_ciphertext_keyring_using_mkp = decrypt_using_key_provider( ciphertext_data=ciphertext_keyring, key_provider=raw_aes_master_key_provider ) @@ -272,12 +264,12 @@ def migration_to_raw_aes_keyring_from_raw_aes_master_key_provider(): # 4. Decrypt the ciphertext_mkp using both the keyring and MKP and ensure the # resulting plaintext is the same and also equal to EXAMPLE_DATA - decrypted_ciphertext_mkp_using_keyring = RawAesKeyring.decrypt_using_keyring( + decrypted_ciphertext_mkp_using_keyring = decrypt_using_keyring( ciphertext_data=ciphertext_mkp, keyring=raw_aes_keyring ) - decrypted_ciphertext_mkp_using_mkp = RawAesMasterKeyProvider.decrypt_using_key_provider( + decrypted_ciphertext_mkp_using_mkp = decrypt_using_key_provider( ciphertext_data=ciphertext_mkp, key_provider=raw_aes_master_key_provider ) diff --git a/examples/src/migration/migration_raw_rsa_key_example.py b/examples/src/migration/migration_raw_rsa_key_example.py index 734cdf075..1167de370 100644 --- a/examples/src/migration/migration_raw_rsa_key_example.py +++ b/examples/src/migration/migration_raw_rsa_key_example.py @@ -12,7 +12,7 @@ The encryption function encrypts the data key under the RSA public key. The decryption function decrypts the data key using the private key. -This example defines classes for Raw RSA Keyring and Raw RSA MKP and +This example creates a Raw RSA Keyring and Raw RSA MKP and then encrypts a custom input EXAMPLE_DATA with an encryption context using both the keyring and MKP. The example then decrypts the ciphertext using both keyring and MKPs. This example also includes some sanity checks for demonstration: @@ -89,77 +89,73 @@ def generate_rsa_keys_helper(): DEFAULT_RSA_PUBLIC_KEY, DEFAULT_RSA_PRIVATE_KEY = generate_rsa_keys_helper() -class RawRsaKeyring(): - """Class for creating a Raw RSA Keyring and using it for encryption and decryption""" +def create_keyring(public_key, private_key): + """Demonstrate how to create a Raw RSA keyring using the key pair. - @staticmethod - def create_keyring(public_key, private_key): - """Demonstrate how to create a Raw RSA keyring using the key pair. + Usage: create_keyring(public_key, private_key) + """ + mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( + config=MaterialProvidersConfig() + ) - Usage: create_keyring(public_key, private_key) - """ - mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( - config=MaterialProvidersConfig() - ) + keyring_input: CreateRawRsaKeyringInput = CreateRawRsaKeyringInput( + key_namespace=DEFAULT_KEY_NAME_SPACE, + key_name=DEFAULT_KEY_NAME, + padding_scheme=PaddingScheme.OAEP_SHA256_MGF1, + public_key=public_key, + private_key=private_key + ) - keyring_input: CreateRawRsaKeyringInput = CreateRawRsaKeyringInput( - key_namespace=DEFAULT_KEY_NAME_SPACE, - key_name=DEFAULT_KEY_NAME, - padding_scheme=PaddingScheme.OAEP_SHA256_MGF1, - public_key=public_key, - private_key=private_key - ) + keyring: IKeyring = mat_prov.create_raw_rsa_keyring( + input=keyring_input + ) - keyring: IKeyring = mat_prov.create_raw_rsa_keyring( - input=keyring_input - ) + return keyring - return keyring - @staticmethod - def encrypt_using_keyring( - plaintext_data: bytes, - keyring: IKeyring - ): - """Demonstrate how to encrypt plaintext data using a Raw RSA keyring. +def encrypt_using_keyring( + plaintext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to encrypt plaintext data using a Raw RSA keyring. - Usage: encrypt_using_keyring(plaintext_data, keyring) - :param plaintext_data: plaintext data you want to encrypt - :type: bytes - :param keyring: Keyring to use for encryption. - :type keyring: IKeyring - """ - client = aws_encryption_sdk.EncryptionSDKClient() + Usage: encrypt_using_keyring(plaintext_data, keyring) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param keyring: Keyring to use for encryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() - ciphertext_data, _ = client.encrypt( - source=plaintext_data, - keyring=keyring, - encryption_context=DEFAULT_ENCRYPTION_CONTEXT - ) + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + keyring=keyring, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) - return ciphertext_data + return ciphertext_data - @staticmethod - def decrypt_using_keyring( - ciphertext_data: bytes, - keyring: IKeyring - ): - """Demonstrate how to decrypt ciphertext data using a Raw RSA keyring. - Usage: decrypt_using_keyring(ciphertext_data, keyring) - :param ciphertext_data: ciphertext data you want to decrypt - :type: bytes - :param keyring: Keyring to use for decryption. - :type keyring: IKeyring - """ - client = aws_encryption_sdk.EncryptionSDKClient() +def decrypt_using_keyring( + ciphertext_data: bytes, + keyring: IKeyring +): + """Demonstrate how to decrypt ciphertext data using a Raw RSA keyring. - decrypted_plaintext_data, _ = client.decrypt( - source=ciphertext_data, - keyring=keyring - ) + Usage: decrypt_using_keyring(ciphertext_data, keyring) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param keyring: Keyring to use for decryption. + :type keyring: IKeyring + """ + client = aws_encryption_sdk.EncryptionSDKClient() - return decrypted_plaintext_data + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + keyring=keyring + ) + + return decrypted_plaintext_data # This is a helper class necessary for the Raw RSA master key provider. @@ -200,88 +196,84 @@ def _get_raw_key(self, key_id): ) -class RawRsaMasterKeyProvider(): - """Class for creating a Raw RSA MKP and using it for encryption and decryption""" +def create_key_provider(): + """Demonstrate how to create a Raw RSA master key provider. - @staticmethod - def create_key_provider(): - """Demonstrate how to create a Raw RSA master key provider. + Usage: create_key_provider() + """ + # Create a Raw RSA master key provider. - Usage: create_key_provider() - """ - # Create a Raw RSA master key provider. - - # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name - # in the Raw keyrings - key_id = DEFAULT_KEY_NAME - - # In this example, we fix the static key to DEFAULT_RSA_PRIVATE_KEY in both the keyring - # and MKP (for MKP, we fix the static key in StaticRandomMasterKeyProvider) in order to make - # the test deterministic. Thus, both the Raw RSA keyring and Raw RSA MKP have the same - # private_key and we are able to encrypt data using keyrings and decrypt using MKP - # and vice versa. In practice, users should generate a new key pair for each key id in - # the StaticRandomMasterKeyProvider. - key_provider = StaticRandomMasterKeyProvider() - key_provider.add_master_key(key_id) - - return key_provider - - @staticmethod - def encrypt_using_key_provider( - plaintext_data: bytes, - key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - ): - """Demonstrate how to encrypt plaintext data using a Raw RSA master key provider. - - Usage: encrypt_using_key_provider(plaintext_data, key_provider) - :param plaintext_data: plaintext data you want to encrypt - :type: bytes - :param key_provider: Master key provider to use for encryption. - :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - """ - client = aws_encryption_sdk.EncryptionSDKClient() + # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name + # in the Raw keyrings + key_id = DEFAULT_KEY_NAME - ciphertext_data, _ = client.encrypt( - source=plaintext_data, - key_provider=key_provider, - encryption_context=DEFAULT_ENCRYPTION_CONTEXT - ) + # In this example, we fix the static key to DEFAULT_RSA_PRIVATE_KEY in both the keyring + # and MKP (for MKP, we fix the static key in StaticRandomMasterKeyProvider) in order to make + # the test deterministic. Thus, both the Raw RSA keyring and Raw RSA MKP have the same + # private_key and we are able to encrypt data using keyrings and decrypt using MKP + # and vice versa. In practice, users should generate a new key pair for each key id in + # the StaticRandomMasterKeyProvider. + key_provider = StaticRandomMasterKeyProvider() + key_provider.add_master_key(key_id) - return ciphertext_data + return key_provider - @staticmethod - def decrypt_using_key_provider( - ciphertext_data: bytes, - key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - ): - """Demonstrate how to decrypt ciphertext data using a Raw RSA master key provider. - Usage: decrypt_using_key_provider(ciphertext_data, key_provider) - :param ciphertext_data: ciphertext data you want to decrypt - :type: bytes - :param key_provider: Master key provider to use for decryption. - :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - """ - client = aws_encryption_sdk.EncryptionSDKClient() +def encrypt_using_key_provider( + plaintext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider +): + """Demonstrate how to encrypt plaintext data using a Raw RSA master key provider. - decrypted_plaintext_data, _ = client.decrypt( - source=ciphertext_data, - key_provider=key_provider - ) + Usage: encrypt_using_key_provider(plaintext_data, key_provider) + :param plaintext_data: plaintext data you want to encrypt + :type: bytes + :param key_provider: Master key provider to use for encryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + ciphertext_data, _ = client.encrypt( + source=plaintext_data, + key_provider=key_provider, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT + ) + + return ciphertext_data + + +def decrypt_using_key_provider( + ciphertext_data: bytes, + key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider +): + """Demonstrate how to decrypt ciphertext data using a Raw RSA master key provider. + + Usage: decrypt_using_key_provider(ciphertext_data, key_provider) + :param ciphertext_data: ciphertext data you want to decrypt + :type: bytes + :param key_provider: Master key provider to use for decryption. + :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider + """ + client = aws_encryption_sdk.EncryptionSDKClient() + + decrypted_plaintext_data, _ = client.decrypt( + source=ciphertext_data, + key_provider=key_provider + ) - return decrypted_plaintext_data + return decrypted_plaintext_data -def migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider( +def migration_raw_rsa_key( public_key=DEFAULT_RSA_PUBLIC_KEY, private_key=DEFAULT_RSA_PRIVATE_KEY ): - """Demonstrate a migration example for moving from a Raw RSA keyring to Raw RSA MKP. + """Demonstrate a migration example for moving to a Raw RSA keyring from Raw RSA MKP. - Usage: migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider(public_key, private_key) + Usage: migration_raw_rsa_key(public_key, private_key) """ # 1a. Create a Raw RSA Keyring - raw_rsa_keyring = RawRsaKeyring.create_keyring(public_key=public_key, private_key=private_key) + raw_rsa_keyring = create_keyring(public_key=public_key, private_key=private_key) # 1b. Create a Raw RSA Master Key Provider @@ -291,16 +283,16 @@ def migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider( # private_key and we are able to encrypt data using keyrings and decrypt using MKP # and vice versa. In practice, users should generate a new key pair for each key id in # the StaticRandomMasterKeyProvider. - raw_rsa_master_key_provider = RawRsaMasterKeyProvider.create_key_provider() + raw_rsa_master_key_provider = create_key_provider() # 2a. Encrypt EXAMPLE_DATA using Raw RSA Keyring - ciphertext_keyring = RawRsaKeyring.encrypt_using_keyring( + ciphertext_keyring = encrypt_using_keyring( plaintext_data=EXAMPLE_DATA, keyring=raw_rsa_keyring ) # 2b. Encrypt EXAMPLE_DATA using Raw RSA Master Key Provider - ciphertext_mkp = RawRsaMasterKeyProvider.encrypt_using_key_provider( + ciphertext_mkp = encrypt_using_key_provider( plaintext_data=EXAMPLE_DATA, key_provider=raw_rsa_master_key_provider ) @@ -312,12 +304,12 @@ def migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider( # 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the # resulting plaintext is the same and also equal to EXAMPLE_DATA - decrypted_ciphertext_keyring_using_keyring = RawRsaKeyring.decrypt_using_keyring( + decrypted_ciphertext_keyring_using_keyring = decrypt_using_keyring( ciphertext_data=ciphertext_keyring, keyring=raw_rsa_keyring ) - decrypted_ciphertext_keyring_using_mkp = RawRsaMasterKeyProvider.decrypt_using_key_provider( + decrypted_ciphertext_keyring_using_mkp = decrypt_using_key_provider( ciphertext_data=ciphertext_keyring, key_provider=raw_rsa_master_key_provider ) @@ -328,12 +320,12 @@ def migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider( # 4. Decrypt the ciphertext_mkp using both the keyring and MKP and ensure the # resulting plaintext is the same and also equal to EXAMPLE_DATA - decrypted_ciphertext_mkp_using_keyring = RawRsaKeyring.decrypt_using_keyring( + decrypted_ciphertext_mkp_using_keyring = decrypt_using_keyring( ciphertext_data=ciphertext_mkp, keyring=raw_rsa_keyring ) - decrypted_ciphertext_mkp_using_mkp = RawRsaMasterKeyProvider.decrypt_using_key_provider( + decrypted_ciphertext_mkp_using_mkp = decrypt_using_key_provider( ciphertext_data=ciphertext_mkp, key_provider=raw_rsa_master_key_provider ) diff --git a/examples/test/migration/test_i_migration_raw_aes_key_example.py b/examples/test/migration/test_i_migration_raw_aes_key_example.py index d068b2231..e0c763cc7 100644 --- a/examples/test/migration/test_i_migration_raw_aes_key_example.py +++ b/examples/test/migration/test_i_migration_raw_aes_key_example.py @@ -4,12 +4,12 @@ import pytest from ...src.migration.migration_raw_aes_key_example import ( - migration_to_raw_aes_keyring_from_raw_aes_master_key_provider, + migration_raw_aes_key, ) pytestmark = [pytest.mark.examples] -def test_migration_to_raw_aes_keyring_from_raw_aes_master_key_provider(): +def test_migration_raw_aes_key(): """Test function for migrating to Raw AES Keyring from Raw AES Master Key Provider.""" - migration_to_raw_aes_keyring_from_raw_aes_master_key_provider() + migration_raw_aes_key() diff --git a/examples/test/migration/test_i_migration_raw_rsa_key_example.py b/examples/test/migration/test_i_migration_raw_rsa_key_example.py index cfe3c3b2a..f1811d6ff 100644 --- a/examples/test/migration/test_i_migration_raw_rsa_key_example.py +++ b/examples/test/migration/test_i_migration_raw_rsa_key_example.py @@ -4,12 +4,12 @@ import pytest from ...src.migration.migration_raw_rsa_key_example import ( - migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider, + migration_raw_rsa_key, ) pytestmark = [pytest.mark.examples] -def test_migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider(): +def test_migration_raw_rsa_key(): """Test function for migrating to Raw RSA Keyring from Raw RSA Master Key Provider.""" - migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider() + migration_raw_rsa_key() From 67d866f9c9cc6c3128d2a67dc5370fb5d484c194 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Fri, 7 Jun 2024 12:39:33 -0700 Subject: [PATCH 07/11] inline encrypt and decrypt --- examples/src/migration/README.rst | 5 +- .../migration_aws_kms_key_example.py | 152 +++--------------- .../migration_raw_aes_key_example.py | 114 ++----------- .../migration_raw_rsa_key_example.py | 122 +++----------- 4 files changed, 56 insertions(+), 337 deletions(-) diff --git a/examples/src/migration/README.rst b/examples/src/migration/README.rst index a709523e9..df98a6fd6 100644 --- a/examples/src/migration/README.rst +++ b/examples/src/migration/README.rst @@ -2,7 +2,7 @@ Migration Examples ################## -The native Python ESDK now uses the `AWS Cryptographic Material Providers Library`_, +The `Encryption SDK for Python`_ now uses the `AWS Cryptographic Material Providers Library`_, which introduces keyrings in place of Master Key Providers. The MPL abstracts lower level cryptographic materials management of encryption and decryption materials. @@ -15,4 +15,5 @@ of the ESDK. Here is the list of examples: 3. Migration example for Raw RSA keys 4. Setting a 'CommitmentPolicy' during migration -.. _AWS Cryptographic Material Providers Library: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/introduction.html \ No newline at end of file +.. _AWS Cryptographic Material Providers Library: https://github.com/aws/aws-cryptographic-material-providers-library +.. _Encryption SDK for Python: https://github.com/aws/aws-encryption-sdk-python/tree/9c34aad60fc918c1a9186ec5215a451e8bfd0f65 \ No newline at end of file diff --git a/examples/src/migration/migration_aws_kms_key_example.py b/examples/src/migration/migration_aws_kms_key_example.py index 9b5efc035..fa3af23dc 100644 --- a/examples/src/migration/migration_aws_kms_key_example.py +++ b/examples/src/migration/migration_aws_kms_key_example.py @@ -40,21 +40,9 @@ } -def create_kms_client(aws_region="us-west-2"): - """Create an AWS KMS client. - - Usage: create_kms_client(aws_region) - :param aws_region: AWS region to use for KMS client. - :type aws_region: string - """ - # Create a boto3 client for KMS. - kms_client = boto3.client('kms', region_name=aws_region) - - return kms_client - - def create_keyring( - kms_key_id: str + kms_key_id: str, + aws_region="us-west-2" ): """Demonstrate how to create an AWS KMS keyring. @@ -66,7 +54,7 @@ def create_keyring( https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id """ # Create a boto3 client for KMS. - kms_client = create_kms_client() + kms_client = boto3.client('kms', region_name=aws_region) # Create a KMS keyring mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( @@ -85,53 +73,6 @@ def create_keyring( return keyring -def encrypt_using_keyring( - plaintext_data: bytes, - keyring: IKeyring, - client: aws_encryption_sdk.EncryptionSDKClient -): - """Demonstrate how to encrypt plaintext data using an AWS KMS keyring. - - Usage: encrypt_using_keyring(plaintext_data, keyring) - :param plaintext_data: plaintext data you want to encrypt - :type: bytes - :param keyring: Keyring to use for encryption. - :type keyring: IKeyring - :param client: AWS Encryption SDK client. - :type client: aws_encryption_sdk.EncryptionSDKClient - """ - ciphertext_data, _ = client.encrypt( - source=plaintext_data, - keyring=keyring, - encryption_context=DEFAULT_ENCRYPTION_CONTEXT - ) - - return ciphertext_data - - -def decrypt_using_keyring( - ciphertext_data: bytes, - keyring: IKeyring, - client: aws_encryption_sdk.EncryptionSDKClient -): - """Demonstrate how to decrypt ciphertext data using an AWS KMS keyring. - - Usage: decrypt_using_keyring(ciphertext_data, keyring) - :param ciphertext_data: ciphertext data you want to decrypt - :type: bytes - :param keyring: Keyring to use for decryption. - :type keyring: IKeyring - :param client: AWS Encryption SDK client. - :type client: aws_encryption_sdk.EncryptionSDKClient - """ - decrypted_plaintext_data, _ = client.decrypt( - source=ciphertext_data, - keyring=keyring - ) - - return decrypted_plaintext_data - - def create_key_provider( kms_key_id: str ): @@ -152,53 +93,6 @@ def create_key_provider( return key_provider -def encrypt_using_key_provider( - plaintext_data: bytes, - key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider, - client: aws_encryption_sdk.EncryptionSDKClient -): - """Demonstrate how to encrypt plaintext data using an AWS KMS master key provider. - - Usage: encrypt_using_key_provider(plaintext_data, key_provider) - :param plaintext_data: plaintext data you want to encrypt - :type: bytes - :param key_provider: Master key provider to use for encryption. - :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - :param client: AWS Encryption SDK client. - :type client: aws_encryption_sdk.EncryptionSDKClient - """ - ciphertext_data, _ = client.encrypt( - source=plaintext_data, - key_provider=key_provider, - encryption_context=DEFAULT_ENCRYPTION_CONTEXT - ) - - return ciphertext_data - - -def decrypt_using_key_provider( - ciphertext_data: bytes, - key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider, - client: aws_encryption_sdk.EncryptionSDKClient -): - """Demonstrate how to decrypt ciphertext data using an AWS KMS master key provider. - - Usage: decrypt_using_key_provider(ciphertext_data, key_provider) - :param ciphertext_data: ciphertext data you want to decrypt - :type: bytes - :param key_provider: Master key provider to use for decryption. - :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - :param client: AWS Encryption SDK client. - :type client: aws_encryption_sdk.EncryptionSDKClient - """ - decrypted_plaintext_data, _ = client.decrypt( - source=ciphertext_data, - key_provider=key_provider - ) - - return decrypted_plaintext_data - - def migration_aws_kms_key( kms_key_id: str ): @@ -221,17 +115,17 @@ def migration_aws_kms_key( aws_kms_master_key_provider = create_key_provider(kms_key_id=kms_key_id) # 2a. Encrypt EXAMPLE_DATA using AWS KMS Keyring - ciphertext_keyring = encrypt_using_keyring( - plaintext_data=EXAMPLE_DATA, + ciphertext_keyring, _ = client.encrypt( + source=EXAMPLE_DATA, keyring=aws_kms_keyring, - client=client + encryption_context=DEFAULT_ENCRYPTION_CONTEXT ) # 2b. Encrypt EXAMPLE_DATA using AWS KMS Master Key Provider - ciphertext_mkp = encrypt_using_key_provider( - plaintext_data=EXAMPLE_DATA, + ciphertext_mkp, _ = client.encrypt( + source=EXAMPLE_DATA, key_provider=aws_kms_master_key_provider, - client=client + encryption_context=DEFAULT_ENCRYPTION_CONTEXT ) # Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP @@ -241,16 +135,14 @@ def migration_aws_kms_key( # 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the # resulting plaintext is the same and also equal to EXAMPLE_DATA - decrypted_ciphertext_keyring_using_keyring = decrypt_using_keyring( - ciphertext_data=ciphertext_keyring, - keyring=aws_kms_keyring, - client=client + decrypted_ciphertext_keyring_using_keyring, _ = client.decrypt( + source=ciphertext_keyring, + keyring=aws_kms_keyring ) - decrypted_ciphertext_keyring_using_mkp = decrypt_using_key_provider( - ciphertext_data=ciphertext_keyring, - key_provider=aws_kms_master_key_provider, - client=client + decrypted_ciphertext_keyring_using_mkp, _ = client.decrypt( + source=ciphertext_keyring, + key_provider=aws_kms_master_key_provider ) assert decrypted_ciphertext_keyring_using_keyring == decrypted_ciphertext_keyring_using_mkp \ @@ -259,16 +151,14 @@ def migration_aws_kms_key( # 4. Decrypt the ciphertext_mkp using both the keyring and MKP and ensure the # resulting plaintext is the same and also equal to EXAMPLE_DATA - decrypted_ciphertext_mkp_using_keyring = decrypt_using_keyring( - ciphertext_data=ciphertext_mkp, - keyring=aws_kms_keyring, - client=client + decrypted_ciphertext_mkp_using_keyring, _ = client.decrypt( + source=ciphertext_mkp, + keyring=aws_kms_keyring ) - decrypted_ciphertext_mkp_using_mkp = decrypt_using_key_provider( - ciphertext_data=ciphertext_mkp, - key_provider=aws_kms_master_key_provider, - client=client + decrypted_ciphertext_mkp_using_mkp, _ = client.decrypt( + source=ciphertext_mkp, + key_provider=aws_kms_master_key_provider ) assert decrypted_ciphertext_mkp_using_keyring == decrypted_ciphertext_mkp_using_mkp \ diff --git a/examples/src/migration/migration_raw_aes_key_example.py b/examples/src/migration/migration_raw_aes_key_example.py index 3a30ad9a3..1da5dab19 100644 --- a/examples/src/migration/migration_raw_aes_key_example.py +++ b/examples/src/migration/migration_raw_aes_key_example.py @@ -80,51 +80,6 @@ def create_keyring(): return keyring -def encrypt_using_keyring( - plaintext_data: bytes, - keyring: IKeyring -): - """Demonstrate how to encrypt plaintext data using a Raw AES keyring. - - Usage: encrypt_using_keyring(plaintext_data, keyring) - :param plaintext_data: plaintext data you want to encrypt - :type: bytes - :param keyring: Keyring to use for encryption. - :type keyring: IKeyring - """ - client = aws_encryption_sdk.EncryptionSDKClient() - - ciphertext_data, _ = client.encrypt( - source=plaintext_data, - keyring=keyring, - encryption_context=DEFAULT_ENCRYPTION_CONTEXT - ) - - return ciphertext_data - - -def decrypt_using_keyring( - ciphertext_data: bytes, - keyring: IKeyring -): - """Demonstrate how to decrypt ciphertext data using a Raw AES keyring. - - Usage: decrypt_using_keyring(ciphertext_data, keyring) - :param ciphertext_data: ciphertext data you want to decrypt - :type: bytes - :param keyring: Keyring to use for decryption. - :type keyring: IKeyring - """ - client = aws_encryption_sdk.EncryptionSDKClient() - - decrypted_plaintext_data, _ = client.decrypt( - source=ciphertext_data, - keyring=keyring - ) - - return decrypted_plaintext_data - - # This is a helper class necessary for the Raw AES master key provider class StaticRandomMasterKeyProvider(RawMasterKeyProvider): """Generates 256-bit keys for each unique key ID.""" @@ -173,56 +128,13 @@ def create_key_provider(): return key_provider -def encrypt_using_key_provider( - plaintext_data: bytes, - key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider -): - """Demonstrate how to encrypt plaintext data using a Raw AES master key provider. - - Usage: encrypt_using_key_provider(plaintext_data, key_provider) - :param plaintext_data: plaintext data you want to encrypt - :type: bytes - :param key_provider: Master key provider to use for encryption. - :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - """ - client = aws_encryption_sdk.EncryptionSDKClient() - - ciphertext_data, _ = client.encrypt( - source=plaintext_data, - key_provider=key_provider, - encryption_context=DEFAULT_ENCRYPTION_CONTEXT - ) - - return ciphertext_data - - -def decrypt_using_key_provider( - ciphertext_data: bytes, - key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider -): - """Demonstrate how to decrypt ciphertext data using a Raw AES master key provider. - - Usage: decrypt_using_key_provider(ciphertext_data, key_provider) - :param ciphertext_data: ciphertext data you want to decrypt - :type: bytes - :param key_provider: Master key provider to use for decryption. - :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - """ - client = aws_encryption_sdk.EncryptionSDKClient() - - decrypted_plaintext_data, _ = client.decrypt( - source=ciphertext_data, - key_provider=key_provider - ) - - return decrypted_plaintext_data - - def migration_raw_aes_key(): """Demonstrate a migration example for moving to a Raw AES keyring from Raw AES MKP. Usage: migration_raw_aes_key() """ + client = aws_encryption_sdk.EncryptionSDKClient() + # 1a. Create a Raw AES Keyring raw_aes_keyring = create_keyring() @@ -230,15 +142,17 @@ def migration_raw_aes_key(): raw_aes_master_key_provider = create_key_provider() # 2a. Encrypt EXAMPLE_DATA using Raw AES Keyring - ciphertext_keyring = encrypt_using_keyring( - plaintext_data=EXAMPLE_DATA, - keyring=raw_aes_keyring + ciphertext_keyring, _ = client.encrypt( + source=EXAMPLE_DATA, + keyring=raw_aes_keyring, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT ) # 2b. Encrypt EXAMPLE_DATA using Raw AES Master Key Provider - ciphertext_mkp = encrypt_using_key_provider( - plaintext_data=EXAMPLE_DATA, - key_provider=raw_aes_master_key_provider + ciphertext_mkp, _ = client.encrypt( + source=EXAMPLE_DATA, + key_provider=raw_aes_master_key_provider, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT ) # Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP @@ -248,13 +162,13 @@ def migration_raw_aes_key(): # 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the # resulting plaintext is the same and also equal to EXAMPLE_DATA - decrypted_ciphertext_keyring_using_keyring = decrypt_using_keyring( - ciphertext_data=ciphertext_keyring, + decrypted_ciphertext_keyring_using_keyring, _ = client.decrypt( + source=ciphertext_keyring, keyring=raw_aes_keyring ) - decrypted_ciphertext_keyring_using_mkp = decrypt_using_key_provider( - ciphertext_data=ciphertext_keyring, + decrypted_ciphertext_keyring_using_mkp, _ = client.decrypt( + source=ciphertext_keyring, key_provider=raw_aes_master_key_provider ) diff --git a/examples/src/migration/migration_raw_rsa_key_example.py b/examples/src/migration/migration_raw_rsa_key_example.py index 1167de370..9f6736383 100644 --- a/examples/src/migration/migration_raw_rsa_key_example.py +++ b/examples/src/migration/migration_raw_rsa_key_example.py @@ -113,51 +113,6 @@ def create_keyring(public_key, private_key): return keyring -def encrypt_using_keyring( - plaintext_data: bytes, - keyring: IKeyring -): - """Demonstrate how to encrypt plaintext data using a Raw RSA keyring. - - Usage: encrypt_using_keyring(plaintext_data, keyring) - :param plaintext_data: plaintext data you want to encrypt - :type: bytes - :param keyring: Keyring to use for encryption. - :type keyring: IKeyring - """ - client = aws_encryption_sdk.EncryptionSDKClient() - - ciphertext_data, _ = client.encrypt( - source=plaintext_data, - keyring=keyring, - encryption_context=DEFAULT_ENCRYPTION_CONTEXT - ) - - return ciphertext_data - - -def decrypt_using_keyring( - ciphertext_data: bytes, - keyring: IKeyring -): - """Demonstrate how to decrypt ciphertext data using a Raw RSA keyring. - - Usage: decrypt_using_keyring(ciphertext_data, keyring) - :param ciphertext_data: ciphertext data you want to decrypt - :type: bytes - :param keyring: Keyring to use for decryption. - :type keyring: IKeyring - """ - client = aws_encryption_sdk.EncryptionSDKClient() - - decrypted_plaintext_data, _ = client.decrypt( - source=ciphertext_data, - keyring=keyring - ) - - return decrypted_plaintext_data - - # This is a helper class necessary for the Raw RSA master key provider. # In the StaticRandomMasterKeyProvider, we fix the static key to # DEFAULT_RSA_PRIVATE_KEY in order to make the test deterministic. @@ -219,51 +174,6 @@ def create_key_provider(): return key_provider -def encrypt_using_key_provider( - plaintext_data: bytes, - key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider -): - """Demonstrate how to encrypt plaintext data using a Raw RSA master key provider. - - Usage: encrypt_using_key_provider(plaintext_data, key_provider) - :param plaintext_data: plaintext data you want to encrypt - :type: bytes - :param key_provider: Master key provider to use for encryption. - :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - """ - client = aws_encryption_sdk.EncryptionSDKClient() - - ciphertext_data, _ = client.encrypt( - source=plaintext_data, - key_provider=key_provider, - encryption_context=DEFAULT_ENCRYPTION_CONTEXT - ) - - return ciphertext_data - - -def decrypt_using_key_provider( - ciphertext_data: bytes, - key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider -): - """Demonstrate how to decrypt ciphertext data using a Raw RSA master key provider. - - Usage: decrypt_using_key_provider(ciphertext_data, key_provider) - :param ciphertext_data: ciphertext data you want to decrypt - :type: bytes - :param key_provider: Master key provider to use for decryption. - :type key_provider: aws_encryption_sdk.key_providers.base.MasterKeyProvider - """ - client = aws_encryption_sdk.EncryptionSDKClient() - - decrypted_plaintext_data, _ = client.decrypt( - source=ciphertext_data, - key_provider=key_provider - ) - - return decrypted_plaintext_data - - def migration_raw_rsa_key( public_key=DEFAULT_RSA_PUBLIC_KEY, private_key=DEFAULT_RSA_PRIVATE_KEY @@ -272,6 +182,8 @@ def migration_raw_rsa_key( Usage: migration_raw_rsa_key(public_key, private_key) """ + client = aws_encryption_sdk.EncryptionSDKClient() + # 1a. Create a Raw RSA Keyring raw_rsa_keyring = create_keyring(public_key=public_key, private_key=private_key) @@ -286,15 +198,17 @@ def migration_raw_rsa_key( raw_rsa_master_key_provider = create_key_provider() # 2a. Encrypt EXAMPLE_DATA using Raw RSA Keyring - ciphertext_keyring = encrypt_using_keyring( - plaintext_data=EXAMPLE_DATA, - keyring=raw_rsa_keyring + ciphertext_keyring = client.encrypt( + source=EXAMPLE_DATA, + keyring=raw_rsa_keyring, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT ) # 2b. Encrypt EXAMPLE_DATA using Raw RSA Master Key Provider - ciphertext_mkp = encrypt_using_key_provider( - plaintext_data=EXAMPLE_DATA, - key_provider=raw_rsa_master_key_provider + ciphertext_mkp = client.encrypt( + source=EXAMPLE_DATA, + key_provider=raw_rsa_master_key_provider, + encryption_context=DEFAULT_ENCRYPTION_CONTEXT ) # Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP @@ -304,13 +218,13 @@ def migration_raw_rsa_key( # 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the # resulting plaintext is the same and also equal to EXAMPLE_DATA - decrypted_ciphertext_keyring_using_keyring = decrypt_using_keyring( - ciphertext_data=ciphertext_keyring, + decrypted_ciphertext_keyring_using_keyring = client.decrypt( + source=ciphertext_keyring, keyring=raw_rsa_keyring ) - decrypted_ciphertext_keyring_using_mkp = decrypt_using_key_provider( - ciphertext_data=ciphertext_keyring, + decrypted_ciphertext_keyring_using_mkp = client.decrypt( + source=ciphertext_keyring, key_provider=raw_rsa_master_key_provider ) @@ -320,13 +234,13 @@ def migration_raw_rsa_key( # 4. Decrypt the ciphertext_mkp using both the keyring and MKP and ensure the # resulting plaintext is the same and also equal to EXAMPLE_DATA - decrypted_ciphertext_mkp_using_keyring = decrypt_using_keyring( - ciphertext_data=ciphertext_mkp, + decrypted_ciphertext_mkp_using_keyring = client.decrypt( + source=ciphertext_mkp, keyring=raw_rsa_keyring ) - decrypted_ciphertext_mkp_using_mkp = decrypt_using_key_provider( - ciphertext_data=ciphertext_mkp, + decrypted_ciphertext_mkp_using_mkp = client.decrypt( + source=ciphertext_mkp, key_provider=raw_rsa_master_key_provider ) From 4c61b23382dec336dd6f80b7ec5e1c9bd4cbe545 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Fri, 7 Jun 2024 12:50:33 -0700 Subject: [PATCH 08/11] fix --- .../src/migration/migration_raw_aes_key_example.py | 8 ++++---- .../src/migration/migration_raw_rsa_key_example.py | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/src/migration/migration_raw_aes_key_example.py b/examples/src/migration/migration_raw_aes_key_example.py index 1da5dab19..2fd2b6f76 100644 --- a/examples/src/migration/migration_raw_aes_key_example.py +++ b/examples/src/migration/migration_raw_aes_key_example.py @@ -178,13 +178,13 @@ def migration_raw_aes_key(): # 4. Decrypt the ciphertext_mkp using both the keyring and MKP and ensure the # resulting plaintext is the same and also equal to EXAMPLE_DATA - decrypted_ciphertext_mkp_using_keyring = decrypt_using_keyring( - ciphertext_data=ciphertext_mkp, + decrypted_ciphertext_mkp_using_keyring, _ = client.decrypt( + source=ciphertext_mkp, keyring=raw_aes_keyring ) - decrypted_ciphertext_mkp_using_mkp = decrypt_using_key_provider( - ciphertext_data=ciphertext_mkp, + decrypted_ciphertext_mkp_using_mkp, _ = client.decrypt( + source=ciphertext_mkp, key_provider=raw_aes_master_key_provider ) diff --git a/examples/src/migration/migration_raw_rsa_key_example.py b/examples/src/migration/migration_raw_rsa_key_example.py index 9f6736383..4a9e52443 100644 --- a/examples/src/migration/migration_raw_rsa_key_example.py +++ b/examples/src/migration/migration_raw_rsa_key_example.py @@ -183,7 +183,7 @@ def migration_raw_rsa_key( Usage: migration_raw_rsa_key(public_key, private_key) """ client = aws_encryption_sdk.EncryptionSDKClient() - + # 1a. Create a Raw RSA Keyring raw_rsa_keyring = create_keyring(public_key=public_key, private_key=private_key) @@ -198,14 +198,14 @@ def migration_raw_rsa_key( raw_rsa_master_key_provider = create_key_provider() # 2a. Encrypt EXAMPLE_DATA using Raw RSA Keyring - ciphertext_keyring = client.encrypt( + ciphertext_keyring, _ = client.encrypt( source=EXAMPLE_DATA, keyring=raw_rsa_keyring, encryption_context=DEFAULT_ENCRYPTION_CONTEXT ) # 2b. Encrypt EXAMPLE_DATA using Raw RSA Master Key Provider - ciphertext_mkp = client.encrypt( + ciphertext_mkp, _ = client.encrypt( source=EXAMPLE_DATA, key_provider=raw_rsa_master_key_provider, encryption_context=DEFAULT_ENCRYPTION_CONTEXT @@ -218,12 +218,12 @@ def migration_raw_rsa_key( # 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the # resulting plaintext is the same and also equal to EXAMPLE_DATA - decrypted_ciphertext_keyring_using_keyring = client.decrypt( + decrypted_ciphertext_keyring_using_keyring, _ = client.decrypt( source=ciphertext_keyring, keyring=raw_rsa_keyring ) - decrypted_ciphertext_keyring_using_mkp = client.decrypt( + decrypted_ciphertext_keyring_using_mkp, _ = client.decrypt( source=ciphertext_keyring, key_provider=raw_rsa_master_key_provider ) @@ -234,12 +234,12 @@ def migration_raw_rsa_key( # 4. Decrypt the ciphertext_mkp using both the keyring and MKP and ensure the # resulting plaintext is the same and also equal to EXAMPLE_DATA - decrypted_ciphertext_mkp_using_keyring = client.decrypt( + decrypted_ciphertext_mkp_using_keyring, _ = client.decrypt( source=ciphertext_mkp, keyring=raw_rsa_keyring ) - decrypted_ciphertext_mkp_using_mkp = client.decrypt( + decrypted_ciphertext_mkp_using_mkp, _ = client.decrypt( source=ciphertext_mkp, key_provider=raw_rsa_master_key_provider ) From 7c721edfa20c15aa9a4c1742d4911ffa8d3bff72 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Fri, 7 Jun 2024 13:57:01 -0700 Subject: [PATCH 09/11] minor fix --- examples/src/migration/migration_aws_kms_key_example.py | 4 ++-- examples/src/migration/migration_raw_aes_key_example.py | 6 +++--- examples/src/migration/migration_raw_rsa_key_example.py | 8 +++++--- .../migration/test_i_migration_aws_kms_key_example.py | 2 +- .../migration/test_i_migration_raw_aes_key_example.py | 4 ++-- .../migration/test_i_migration_raw_rsa_key_example.py | 4 ++-- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/examples/src/migration/migration_aws_kms_key_example.py b/examples/src/migration/migration_aws_kms_key_example.py index fa3af23dc..28b8193e3 100644 --- a/examples/src/migration/migration_aws_kms_key_example.py +++ b/examples/src/migration/migration_aws_kms_key_example.py @@ -5,8 +5,8 @@ The AWS KMS keyring uses symmetric encryption KMS keys to generate, encrypt and decrypt data keys. This example creates a KMS Keyring and KMS MKP and -then encrypts a custom input EXAMPLE_DATA with an encryption context using both -the keyring and MKP. The example then decrypts the ciphertext using both keyring and MKPs. +then encrypts a custom input EXAMPLE_DATA with the same encryption context using both +the keyring and MKP. The example then decrypts the ciphertexts using both keyring and MKPs. This example also includes some sanity checks for demonstration: 1. Decryption of these ciphertexts encrypted using keyring and MKP is possible using both KMS keyring and KMS MKP diff --git a/examples/src/migration/migration_raw_aes_key_example.py b/examples/src/migration/migration_raw_aes_key_example.py index 2fd2b6f76..f26b3b4a0 100644 --- a/examples/src/migration/migration_raw_aes_key_example.py +++ b/examples/src/migration/migration_raw_aes_key_example.py @@ -9,11 +9,11 @@ when you need to provide the wrapping key and encrypt the data keys locally or offline. This example creates a Raw AES Keyring and Raw AES MKP and -then encrypts a custom input EXAMPLE_DATA with an encryption context using both -the keyring and MKP. The example then decrypts the ciphertext using both keyring and MKPs. +then encrypts a custom input EXAMPLE_DATA with the same encryption context using both +the keyring and MKP. The example then decrypts the ciphertexts using both keyring and MKPs. This example also includes some sanity checks for demonstration: 1. Decryption of these ciphertexts encrypted using keyring and MKP - is possible using both KMS keyring and KMS MKP + is possible using both Raw AES keyring and Raw AES MKP 2. Both decrypted plaintexts are same and match EXAMPLE_DATA These sanity checks are for demonstration in the example only. You do not need these in your code. diff --git a/examples/src/migration/migration_raw_rsa_key_example.py b/examples/src/migration/migration_raw_rsa_key_example.py index 4a9e52443..fb6bd98b4 100644 --- a/examples/src/migration/migration_raw_rsa_key_example.py +++ b/examples/src/migration/migration_raw_rsa_key_example.py @@ -13,11 +13,11 @@ decrypts the data key using the private key. This example creates a Raw RSA Keyring and Raw RSA MKP and -then encrypts a custom input EXAMPLE_DATA with an encryption context using both -the keyring and MKP. The example then decrypts the ciphertext using both keyring and MKPs. +then encrypts a custom input EXAMPLE_DATA with the same encryption context using both +the keyring and MKP. The example then decrypts the ciphertexts using both keyring and MKPs. This example also includes some sanity checks for demonstration: 1. Decryption of these ciphertexts encrypted using keyring and MKP - is possible using both KMS keyring and KMS MKP + is possible using both Raw RSA keyring and Raw RSA MKP 2. Both decrypted plaintexts are same and match EXAMPLE_DATA These sanity checks are for demonstration in the example only. You do not need these in your code. @@ -142,6 +142,8 @@ def _get_raw_key(self, key_id): except KeyError: # We fix the static key in order to make the test deterministic # In practice, you should get this key from a secure key management system such as an HSM. + # Also, in practice, users should generate a new key pair for each key id in + # the StaticRandomMasterKeyProvider. static_key = DEFAULT_RSA_PRIVATE_KEY self._static_keys[key_id] = static_key return WrappingKey( diff --git a/examples/test/migration/test_i_migration_aws_kms_key_example.py b/examples/test/migration/test_i_migration_aws_kms_key_example.py index 56202ad71..d4cf49ce9 100644 --- a/examples/test/migration/test_i_migration_aws_kms_key_example.py +++ b/examples/test/migration/test_i_migration_aws_kms_key_example.py @@ -11,6 +11,6 @@ def test_migration_aws_kms_key(): - """Test function for migrating using AWS KMS Keys.""" + """Test function for migration of AWS KMS Keys.""" kms_key_id = "arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f" migration_aws_kms_key(kms_key_id) diff --git a/examples/test/migration/test_i_migration_raw_aes_key_example.py b/examples/test/migration/test_i_migration_raw_aes_key_example.py index e0c763cc7..7601e7dc0 100644 --- a/examples/test/migration/test_i_migration_raw_aes_key_example.py +++ b/examples/test/migration/test_i_migration_raw_aes_key_example.py @@ -1,6 +1,6 @@ # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -"""Test suite for the migration_to_raw_aes_keyring_from_raw_aes_master_key_provider_example.""" +"""Test suite for the migration_raw_aes_key_example.""" import pytest from ...src.migration.migration_raw_aes_key_example import ( @@ -11,5 +11,5 @@ def test_migration_raw_aes_key(): - """Test function for migrating to Raw AES Keyring from Raw AES Master Key Provider.""" + """Test function for migration of Raw AES keys.""" migration_raw_aes_key() diff --git a/examples/test/migration/test_i_migration_raw_rsa_key_example.py b/examples/test/migration/test_i_migration_raw_rsa_key_example.py index f1811d6ff..9e111d25a 100644 --- a/examples/test/migration/test_i_migration_raw_rsa_key_example.py +++ b/examples/test/migration/test_i_migration_raw_rsa_key_example.py @@ -1,6 +1,6 @@ # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -"""Test suite for the migration_to_raw_rsa_keyring_from_raw_rsa_master_key_provider_example.""" +"""Test suite for the migration_raw_rsa_key_example.""" import pytest from ...src.migration.migration_raw_rsa_key_example import ( @@ -11,5 +11,5 @@ def test_migration_raw_rsa_key(): - """Test function for migrating to Raw RSA Keyring from Raw RSA Master Key Provider.""" + """Test function for migration of Raw RSA keys.""" migration_raw_rsa_key() From 6d44ed11e3bd019e06e702ee126ca7cbfa4fcd6e Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Mon, 10 Jun 2024 10:18:28 -0700 Subject: [PATCH 10/11] fix comments --- examples/src/migration/README.rst | 23 ++++++----- .../migration_raw_aes_key_example.py | 26 ++++++++++--- .../migration_raw_rsa_key_example.py | 38 +++++++++++-------- 3 files changed, 56 insertions(+), 31 deletions(-) diff --git a/examples/src/migration/README.rst b/examples/src/migration/README.rst index df98a6fd6..0a25d68ec 100644 --- a/examples/src/migration/README.rst +++ b/examples/src/migration/README.rst @@ -2,18 +2,21 @@ Migration Examples ################## -The `Encryption SDK for Python`_ now uses the `AWS Cryptographic Material Providers Library`_, -which introduces keyrings in place of Master Key Providers. The MPL abstracts lower +The `Encryption SDK for Python`_ now uses the `AWS Cryptographic Material Providers Library`_. The MPL abstracts lower level cryptographic materials management of encryption and decryption materials. -This directory contains some examples to migrate from the old version of the ESDK. -If you have messages encrypted in the older versions using Master Key Providers, -these examples can guide you on how to decrypt those messages using the new version -of the ESDK. Here is the list of examples: -1. Migration example for AWS KMS keys -2. Migration example for Raw AES keys -3. Migration example for Raw RSA keys -4. Setting a 'CommitmentPolicy' during migration +This directory contains migration examples for: + +* Moving to Keyrings from Master Key Providers: + #. Migration example to AWS KMS keyring from AWS KMS Master Key Provider. + #. Migration example to Raw AES keyring from Raw AES Master Key Provider. + #. Migration example to Raw RSA keyring from Raw RSA Master Key Provider. + +* Migration to newer versions of the ESDK from the old version (1.x): + #. Setting a 'CommitmentPolicy' during migration. + If you have messages encrypted in the older versions of the ESDK (1.x), + this example can guide you on how to decrypt those messages using the + new version of the ESDK. .. _AWS Cryptographic Material Providers Library: https://github.com/aws/aws-cryptographic-material-providers-library .. _Encryption SDK for Python: https://github.com/aws/aws-encryption-sdk-python/tree/9c34aad60fc918c1a9186ec5215a451e8bfd0f65 \ No newline at end of file diff --git a/examples/src/migration/migration_raw_aes_key_example.py b/examples/src/migration/migration_raw_aes_key_example.py index f26b3b4a0..53364cbab 100644 --- a/examples/src/migration/migration_raw_aes_key_example.py +++ b/examples/src/migration/migration_raw_aes_key_example.py @@ -49,8 +49,12 @@ DEFAULT_AES_256_STATIC_KEY = secrets.token_bytes(32) +# The key namespace in the Raw keyrings is equivalent to Provider ID (or Provider) field +# in the Raw Master Key Providers DEFAULT_KEY_NAME_SPACE = "Some managed raw keys" +# The key name in the Raw keyrings is equivalent to the Key ID field +# in the Raw Master Key Providers DEFAULT_KEY_NAME = "My 256-bit AES wrapping key" @@ -66,6 +70,10 @@ def create_keyring(): config=MaterialProvidersConfig() ) + # The key namespace in the Raw keyrings is equivalent to Provider ID (or Provider) field + # in the Raw Master Key Providers + # The key name in the Raw keyrings is equivalent to the Key ID field + # in the Raw Master Key Providers keyring_input: CreateRawAesKeyringInput = CreateRawAesKeyringInput( key_namespace=DEFAULT_KEY_NAME_SPACE, key_name=DEFAULT_KEY_NAME, @@ -81,11 +89,16 @@ def create_keyring(): # This is a helper class necessary for the Raw AES master key provider -class StaticRandomMasterKeyProvider(RawMasterKeyProvider): +# In the StaticMasterKeyProvider, we fix the static key to +# DEFAULT_AES_256_STATIC_KEY in order to make the test deterministic. +# Thus, both the Raw AES keyring and Raw AES MKP have the same key +# and we are able to encrypt data using keyrings and decrypt using MKP and vice versa +# In practice, users should generate a new random key for each key id. +class StaticMasterKeyProvider(RawMasterKeyProvider): """Generates 256-bit keys for each unique key ID.""" - # The Provider ID (or Provider) field in the JceMasterKey and RawMasterKey is - # equivalent to key namespace in the Raw keyrings + # The key namespace in the Raw keyrings is equivalent to Provider ID (or Provider) field + # in the Raw Master Key Providers provider_id = DEFAULT_KEY_NAME_SPACE def __init__(self, **kwargs): # pylint: disable=unused-argument @@ -93,7 +106,7 @@ def __init__(self, **kwargs): # pylint: disable=unused-argument self._static_keys = {} def _get_raw_key(self, key_id): - """Returns a static, randomly-generated symmetric key for the specified key ID. + """Returns a static, symmetric key for the specified key ID. :param str key_id: Key ID :returns: Wrapping key that contains the specified static key @@ -120,9 +133,10 @@ def create_key_provider(): """ # Create a Raw AES master key provider. - # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name in the Raw keyrings + # The key name in the Raw keyrings is equivalent to the Key ID field + # in the Raw Master Key Providers key_id = DEFAULT_KEY_NAME - key_provider = StaticRandomMasterKeyProvider() + key_provider = StaticMasterKeyProvider() key_provider.add_master_key(key_id) return key_provider diff --git a/examples/src/migration/migration_raw_rsa_key_example.py b/examples/src/migration/migration_raw_rsa_key_example.py index fb6bd98b4..8333e25b4 100644 --- a/examples/src/migration/migration_raw_rsa_key_example.py +++ b/examples/src/migration/migration_raw_rsa_key_example.py @@ -52,8 +52,12 @@ "the data you are handling": "is what you think it is", } +# The key namespace in the Raw keyrings is equivalent to Provider ID (or Provider) field +# in the Raw Master Key Providers DEFAULT_KEY_NAME_SPACE = "Some managed raw keys" +# The key name in the Raw keyrings is equivalent to the Key ID field +# in the Raw Master Key Providers DEFAULT_KEY_NAME = "My 4096-bit RSA wrapping key" @@ -98,6 +102,10 @@ def create_keyring(public_key, private_key): config=MaterialProvidersConfig() ) + # The key namespace in the Raw keyrings is equivalent to Provider ID (or Provider) field + # in the Raw Master Key Providers + # The key name in the Raw keyrings is equivalent to the Key ID field + # in the Raw Master Key Providers keyring_input: CreateRawRsaKeyringInput = CreateRawRsaKeyringInput( key_namespace=DEFAULT_KEY_NAME_SPACE, key_name=DEFAULT_KEY_NAME, @@ -114,16 +122,16 @@ def create_keyring(public_key, private_key): # This is a helper class necessary for the Raw RSA master key provider. -# In the StaticRandomMasterKeyProvider, we fix the static key to +# In the StaticMasterKeyProvider, we fix the static key to # DEFAULT_RSA_PRIVATE_KEY in order to make the test deterministic. # Thus, both the Raw RSA keyring and Raw RSA MKP have the same private_key # and we are able to encrypt data using keyrings and decrypt using MKP and vice versa -# In practice, users should generate a new key pair for each key id. -class StaticRandomMasterKeyProvider(RawMasterKeyProvider): - """Randomly generates and provides 4096-bit RSA keys consistently per unique key id.""" +# In practice, users should generate a new random key pair for each key id. +class StaticMasterKeyProvider(RawMasterKeyProvider): + """Provides 4096-bit RSA keys consistently per unique key id.""" - # The Provider ID (or Provider) field in the JceMasterKey and RawMasterKey is - # equivalent to key namespace in the Raw keyrings + # The key namespace in the Raw keyrings is equivalent to Provider ID (or Provider) field + # in the Raw Master Key Providers provider_id = DEFAULT_KEY_NAME_SPACE def __init__(self, **kwargs): # pylint: disable=unused-argument @@ -131,7 +139,7 @@ def __init__(self, **kwargs): # pylint: disable=unused-argument self._static_keys = {} def _get_raw_key(self, key_id): - """Retrieves a static, randomly generated, RSA key for the specified key id. + """Retrieves a static, RSA key for the specified key id. :param str key_id: User-defined ID for the static key :returns: Wrapping key that contains the specified static key @@ -143,7 +151,7 @@ def _get_raw_key(self, key_id): # We fix the static key in order to make the test deterministic # In practice, you should get this key from a secure key management system such as an HSM. # Also, in practice, users should generate a new key pair for each key id in - # the StaticRandomMasterKeyProvider. + # the StaticMasterKeyProvider. static_key = DEFAULT_RSA_PRIVATE_KEY self._static_keys[key_id] = static_key return WrappingKey( @@ -160,17 +168,17 @@ def create_key_provider(): """ # Create a Raw RSA master key provider. - # The Key ID field in the JceMasterKey and RawMasterKey is equivalent to key name - # in the Raw keyrings + # The key name in the Raw keyrings is equivalent to the Key ID field + # in the Raw Master Key Providers key_id = DEFAULT_KEY_NAME # In this example, we fix the static key to DEFAULT_RSA_PRIVATE_KEY in both the keyring - # and MKP (for MKP, we fix the static key in StaticRandomMasterKeyProvider) in order to make + # and MKP (for MKP, we fix the static key in StaticMasterKeyProvider) in order to make # the test deterministic. Thus, both the Raw RSA keyring and Raw RSA MKP have the same # private_key and we are able to encrypt data using keyrings and decrypt using MKP # and vice versa. In practice, users should generate a new key pair for each key id in - # the StaticRandomMasterKeyProvider. - key_provider = StaticRandomMasterKeyProvider() + # the StaticMasterKeyProvider. + key_provider = StaticMasterKeyProvider() key_provider.add_master_key(key_id) return key_provider @@ -192,11 +200,11 @@ def migration_raw_rsa_key( # 1b. Create a Raw RSA Master Key Provider # In this example, we fix the static key to DEFAULT_RSA_PRIVATE_KEY in both the keyring - # and MKP (for MKP, we fix the static key in StaticRandomMasterKeyProvider) in order to make + # and MKP (for MKP, we fix the static key in StaticMasterKeyProvider) in order to make # the test deterministic. Thus, both the Raw RSA keyring and Raw RSA MKP have the same # private_key and we are able to encrypt data using keyrings and decrypt using MKP # and vice versa. In practice, users should generate a new key pair for each key id in - # the StaticRandomMasterKeyProvider. + # the StaticMasterKeyProvider. raw_rsa_master_key_provider = create_key_provider() # 2a. Encrypt EXAMPLE_DATA using Raw RSA Keyring From 2da41df13474314363002c634609822970c02ca1 Mon Sep 17 00:00:00 2001 From: Ritvik Kapila Date: Wed, 12 Jun 2024 20:12:04 -0700 Subject: [PATCH 11/11] fix --- examples/src/migration/README.rst | 15 ++++++--------- .../migration/migration_raw_aes_key_example.py | 4 ++-- .../migration/migration_raw_rsa_key_example.py | 4 ++-- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/examples/src/migration/README.rst b/examples/src/migration/README.rst index 0a25d68ec..41d3f5515 100644 --- a/examples/src/migration/README.rst +++ b/examples/src/migration/README.rst @@ -7,16 +7,13 @@ level cryptographic materials management of encryption and decryption materials. This directory contains migration examples for: -* Moving to Keyrings from Master Key Providers: - #. Migration example to AWS KMS keyring from AWS KMS Master Key Provider. - #. Migration example to Raw AES keyring from Raw AES Master Key Provider. - #. Migration example to Raw RSA keyring from Raw RSA Master Key Provider. +#. Moving to Keyrings from Master Key Providers: + * Migration example to AWS KMS keyring from AWS KMS Master Key Provider. + * Migration example to Raw AES keyring from Raw AES Master Key Provider. + * Migration example to Raw RSA keyring from Raw RSA Master Key Provider. -* Migration to newer versions of the ESDK from the old version (1.x): - #. Setting a 'CommitmentPolicy' during migration. - If you have messages encrypted in the older versions of the ESDK (1.x), - this example can guide you on how to decrypt those messages using the - new version of the ESDK. +#. Migration to newer versions of the ESDK (4.x+) from 1.x versions: + * Setting a 'CommitmentPolicy' during migration - If you have messages encrypted with 1.x versions of the ESDK (i.e. not using key commitment) and want to migrate to encrypt with key commitment using the keyring providers introduced in ESDK 4.x, this example will guide you on how to decrypt those messages using the new version of the ESDK. .. _AWS Cryptographic Material Providers Library: https://github.com/aws/aws-cryptographic-material-providers-library .. _Encryption SDK for Python: https://github.com/aws/aws-encryption-sdk-python/tree/9c34aad60fc918c1a9186ec5215a451e8bfd0f65 \ No newline at end of file diff --git a/examples/src/migration/migration_raw_aes_key_example.py b/examples/src/migration/migration_raw_aes_key_example.py index 53364cbab..772f83cf5 100644 --- a/examples/src/migration/migration_raw_aes_key_example.py +++ b/examples/src/migration/migration_raw_aes_key_example.py @@ -19,7 +19,7 @@ Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP are not the same because the ESDK generates different data keys each time for encryption of the data. -But both ciphertexts when decrypted using keyring and MKP should give the same plaintext result. +But both ciphertexts when decrypted using keyring and MKP will give the same plaintext result. For more information on how to use Raw AES keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-aes-keyring.html @@ -172,7 +172,7 @@ def migration_raw_aes_key(): # Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP # (that is ciphertext_keyring and ciphertext_mkp) are not the same because the ESDK # generates different data keys each time for encryption of the data. But both - # ciphertexts when decrypted using keyring and MKP should give the same plaintext result. + # ciphertexts when decrypted using keyring and MKP will give the same plaintext result. # 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the # resulting plaintext is the same and also equal to EXAMPLE_DATA diff --git a/examples/src/migration/migration_raw_rsa_key_example.py b/examples/src/migration/migration_raw_rsa_key_example.py index 8333e25b4..7c6020a53 100644 --- a/examples/src/migration/migration_raw_rsa_key_example.py +++ b/examples/src/migration/migration_raw_rsa_key_example.py @@ -23,7 +23,7 @@ Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP are not the same because the ESDK generates different data keys each time for encryption of the data. -But both ciphertexts when decrypted using keyring and MKP should give the same plaintext result. +But both ciphertexts when decrypted using keyring and MKP will give the same plaintext result. For more information on how to use Raw RSA keyrings, see https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-raw-rsa-keyring.html @@ -224,7 +224,7 @@ def migration_raw_rsa_key( # Note: The ciphertexts obtained by encrypting EXAMPLE_DATA using keyring and MKP # (that is ciphertext_keyring and ciphertext_mkp) are not the same because the ESDK # generates different data keys each time for encryption of the data. But both - # ciphertexts when decrypted using keyring and MKP should give the same plaintext result. + # ciphertexts when decrypted using keyring and MKP will give the same plaintext result. # 3. Decrypt the ciphertext_keyring using both the keyring and MKP and ensure the # resulting plaintext is the same and also equal to EXAMPLE_DATA