def test_raw_aes_encryption_decryption(encryption_materials_samples): # Initializing attributes key_namespace = _PROVIDER_ID key_name = _KEY_ID # Creating an instance of a raw AES keyring test_raw_aes_keyring = RawAESKeyring( key_namespace=key_namespace, key_name=key_name, wrapping_key=_WRAPPING_KEY, ) # Call on_encrypt function for the keyring encryption_materials = test_raw_aes_keyring.on_encrypt( encryption_materials=encryption_materials_samples) # Generate decryption materials decryption_materials = DecryptionMaterials( algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, verification_key=b"ex_verification_key", encryption_context=_ENCRYPTION_CONTEXT, ) # Call on_decrypt function for the keyring decryption_materials = test_raw_aes_keyring.on_decrypt( decryption_materials=decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys) # Check if the data keys match assert encryption_materials.data_encryption_key.data_key == decryption_materials.data_encryption_key.data_key
def test_aws_kms_single_cmk_keyring_on_decrypt_multiple_cmk(fake_generator_and_child): generator, child = fake_generator_and_child encrypting_keyring = AwsKmsKeyring(generator_key_id=generator, key_ids=(child,)) decrypting_keyring = _AwsKmsSingleCmkKeyring(key_id=child, client_supplier=DefaultClientSupplier()) initial_encryption_materials = EncryptionMaterials(algorithm=ALGORITHM, encryption_context={}) encryption_materials = encrypting_keyring.on_encrypt(initial_encryption_materials) initial_decryption_materials = DecryptionMaterials( algorithm=encryption_materials.algorithm, encryption_context=encryption_materials.encryption_context ) result_materials = decrypting_keyring.on_decrypt( decryption_materials=initial_decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys ) generator_flags = _matching_flags( MasterKeyInfo(provider_id=KEY_NAMESPACE, key_info=generator), result_materials.keyring_trace ) assert len(generator_flags) == 0 child_flags = _matching_flags( MasterKeyInfo(provider_id=KEY_NAMESPACE, key_info=child), result_materials.keyring_trace ) assert KeyringTraceFlag.DECRYPTED_DATA_KEY in child_flags assert KeyringTraceFlag.VERIFIED_ENCRYPTION_CONTEXT in child_flags
def test_private_key_can_decrypt(): complete_keyring = RawRSAKeyring( key_namespace=_PROVIDER_ID, key_name=_KEY_ID, wrapping_algorithm=_WRAPPING_ALGORITHM, private_wrapping_key=_PRIVATE_WRAPPING_KEY, public_wrapping_key=_PUBLIC_WRAPPING_KEY, ) test_keyring = RawRSAKeyring( key_namespace=_PROVIDER_ID, key_name=_KEY_ID, wrapping_algorithm=_WRAPPING_ALGORITHM, private_wrapping_key=_PRIVATE_WRAPPING_KEY, ) initial_materials = EncryptionMaterials( algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, encryption_context=_ENCRYPTION_CONTEXT) encryption_materials = complete_keyring.on_encrypt(initial_materials) initial_decryption_materials = DecryptionMaterials( algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, encryption_context=_ENCRYPTION_CONTEXT) test_materials = test_keyring.on_decrypt( decryption_materials=initial_decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys) assert test_materials is not initial_decryption_materials assert test_materials.data_encryption_key is not None
def test_aws_kms_single_cmk_keyring_on_decrypt_existing_datakey(caplog): # In this context there are no KMS CMKs, so any calls to KMS will fail. caplog.set_level(logging.DEBUG) keyring = _AwsKmsSingleCmkKeyring(key_id="foo", client_supplier=DefaultClientSupplier()) initial_materials = DecryptionMaterials( algorithm=ALGORITHM, encryption_context={}, data_encryption_key=RawDataKey( key_provider=MasterKeyInfo(provider_id="foo", key_info=b"bar"), data_key=os.urandom(ALGORITHM.kdf_input_len) ), ) result_materials = keyring.on_decrypt( decryption_materials=initial_materials, encrypted_data_keys=( EncryptedDataKey( key_provider=MasterKeyInfo(provider_id=KEY_NAMESPACE, key_info=b"foo"), encrypted_data_key=b"bar" ), ), ) assert result_materials.data_encryption_key == initial_materials.data_encryption_key log_data = caplog.text # This means that it did NOT try to decrypt the EDK. assert "Unable to decrypt encrypted data key from" not in log_data
def decrypt_materials(self, request): """Obtains a plaintext data key from one or more encrypted data keys using underlying master key provider. :param request: decrypt materials request :type request: aws_encryption_sdk.materials_managers.DecryptionMaterialsRequest :returns: decryption materials :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials """ try: return super(MrcryptLegacyCompatibilityCryptoMaterialsManager, self).decrypt_materials(request) except (AWSEncryptionSDKClientError, KeyError): _LOGGER.debug( 'Encountered error decrypting materials with DefaultCryptoMaterialsManager.' ' Attempting to decrypt using uncompressed elliptic curve point.' ) # Once this issue is addressed, the caught exception classes should be narrowed appropriately: # https://github.com/awslabs/aws-encryption-sdk-python/issues/21 _LOGGER.warning( "This file is encrypted using an uncompressed key, which may lead to compatibility issues " "with the AWS Encryption SDK.") data_key = self.master_key_provider.decrypt_data_key_from_list( # subclasses confuse pylint: disable=no-member encrypted_data_keys=request.encrypted_data_keys, algorithm=request.algorithm, encryption_context=request.encryption_context) verification_key = self._load_uncompressed_verification_key_from_encryption_context( algorithm=request.algorithm, encryption_context=request.encryption_context) return DecryptionMaterials(data_key=data_key, verification_key=verification_key)
def _break_decryption_materials(self, decryption_materials): # type: (DecryptionMaterials) -> DecryptionMaterials return DecryptionMaterials( algorithm=self._broken_algorithm(decryption_materials.algorithm), data_encryption_key=decryption_materials.data_encryption_key, encryption_context=self._broken_encryption_context( decryption_materials.encryption_context), verification_key=self._broken_key( decryption_materials.verification_key), keyring_trace=decryption_materials.keyring_trace, )
def test_multi_keyring_encryption_decryption(multi_keyring, encryption_materials): # Call on_encrypt function for the keyring encryption_materials = multi_keyring.on_encrypt(encryption_materials) # Generate decryption materials decryption_materials = DecryptionMaterials( algorithm=ALGORITHM, verification_key=b"ex_verification_key", encryption_context=_ENCRYPTION_CONTEXT) # Call on_decrypt function for the keyring decryption_materials = multi_keyring.on_decrypt( decryption_materials=decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys) # Check if the data keys match assert encryption_materials.data_encryption_key == decryption_materials.data_encryption_key
def test_raw_keyring_decrypts_what_raw_master_key_encrypts( encryption_materials_samples): # Create instance of raw master key test_raw_master_key = RawMasterKey( key_id=_KEY_ID, provider_id=_PROVIDER_ID, wrapping_key=WrappingKey( wrapping_algorithm=_WRAPPING_ALGORITHM, wrapping_key=_PRIVATE_WRAPPING_KEY_PEM, wrapping_key_type=EncryptionKeyType.PRIVATE, ), ) test_raw_rsa_keyring = RawRSAKeyring.from_pem_encoding( key_namespace=_PROVIDER_ID, key_name=_KEY_ID, wrapping_algorithm=_WRAPPING_ALGORITHM, private_encoded_key=_PRIVATE_WRAPPING_KEY_PEM, public_encoded_key=_PUBLIC_WRAPPING_KEY_PEM, ) raw_mkp_generated_data_key = test_raw_master_key.generate_data_key( algorithm=encryption_materials_samples.algorithm, encryption_context=encryption_materials_samples.encryption_context, ) raw_mkp_encrypted_data_key = test_raw_master_key.encrypt_data_key( data_key=raw_mkp_generated_data_key, algorithm=encryption_materials_samples.algorithm, encryption_context=encryption_materials_samples.encryption_context, ) decryption_materials = test_raw_rsa_keyring.on_decrypt( decryption_materials=DecryptionMaterials( algorithm=encryption_materials_samples.algorithm, encryption_context=encryption_materials_samples.encryption_context, verification_key=b"ex_verification_key", ), encrypted_data_keys=[raw_mkp_encrypted_data_key], ) assert raw_mkp_generated_data_key.data_key == decryption_materials.data_encryption_key.data_key
def get_decryption_materials_with_data_encryption_key(): return DecryptionMaterials( algorithm=AlgorithmSuite.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, data_encryption_key=RawDataKey( key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_EXISTING_KEY_ID), data_key= b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', ), encryption_context=_ENCRYPTION_CONTEXT, verification_key=b"ex_verification_key", keyring_trace=[ KeyringTrace( wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_EXISTING_KEY_ID), flags={KeyringTraceFlag.DECRYPTED_DATA_KEY}, ) ], )
def test_aws_kms_single_cmk_keyring_on_decrypt_no_match(fake_generator_and_child): generator, child = fake_generator_and_child encrypting_keyring = _AwsKmsSingleCmkKeyring(key_id=generator, client_supplier=DefaultClientSupplier()) decrypting_keyring = _AwsKmsSingleCmkKeyring(key_id=child, client_supplier=DefaultClientSupplier()) initial_encryption_materials = EncryptionMaterials(algorithm=ALGORITHM, encryption_context={}) encryption_materials = encrypting_keyring.on_encrypt(initial_encryption_materials) initial_decryption_materials = DecryptionMaterials( algorithm=encryption_materials.algorithm, encryption_context=encryption_materials.encryption_context ) result_materials = decrypting_keyring.on_decrypt( decryption_materials=initial_decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys ) assert result_materials.data_encryption_key is None
def test_aws_kms_discovery_keyring_on_decrypt_no_matching_edk(caplog): # In this context there are no KMS CMKs, so any calls to KMS will fail. caplog.set_level(logging.DEBUG) keyring = _AwsKmsDiscoveryKeyring(client_supplier=DefaultClientSupplier()) initial_materials = DecryptionMaterials(algorithm=ALGORITHM, encryption_context={},) result_materials = keyring.on_decrypt( decryption_materials=initial_materials, encrypted_data_keys=( EncryptedDataKey(key_provider=MasterKeyInfo(provider_id="foo", key_info=b"bar"), encrypted_data_key=b"bar"), ), ) assert result_materials.data_encryption_key is None log_data = caplog.text # This means that it did NOT try to decrypt the EDK. assert "Unable to decrypt encrypted data key from" not in log_data
def _decrypt_materials_using_master_key_provider(self, request): """Obtains a plaintext data key from one or more encrypted data keys using underlying master key provider. :param request: decrypt materials request :type request: aws_encryption_sdk.materials_managers.DecryptionMaterialsRequest :returns: decryption materials :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials """ data_key = self.master_key_provider.decrypt_data_key_from_list( encrypted_data_keys=request.encrypted_data_keys, algorithm=request.algorithm, encryption_context=request.encryption_context, ) verification_key = self._load_verification_key_from_encryption_context( algorithm=request.algorithm, encryption_context=request.encryption_context) return DecryptionMaterials(data_key=data_key, verification_key=verification_key)
def test_raw_keyring_decrypts_what_raw_master_key_encrypts( encryption_materials_samples): # Initializing attributes key_namespace = _PROVIDER_ID key_name = _KEY_ID # Creating an instance of a raw AES keyring test_raw_aes_keyring = RawAESKeyring( key_namespace=key_namespace, key_name=key_name, wrapping_key=_WRAPPING_KEY, ) # Creating an instance of a raw master key test_raw_master_key = RawMasterKey( key_id=test_raw_aes_keyring.key_name, provider_id=test_raw_aes_keyring.key_namespace, wrapping_key=test_raw_aes_keyring._wrapping_key_structure, ) if encryption_materials_samples.data_encryption_key is None: return raw_master_key_encrypted_data_key = test_raw_master_key.encrypt_data_key( data_key=encryption_materials_samples.data_encryption_key, algorithm=encryption_materials_samples.algorithm, encryption_context=encryption_materials_samples.encryption_context, ) # Check if plaintext data key encrypted by raw master key is decrypted by raw keyring raw_aes_keyring_decrypted_data_key = test_raw_aes_keyring.on_decrypt( decryption_materials=DecryptionMaterials( algorithm=encryption_materials_samples.algorithm, encryption_context=encryption_materials_samples.encryption_context, verification_key=b"ex_verification_key", ), encrypted_data_keys=[raw_master_key_encrypted_data_key], ).data_encryption_key.data_key assert encryption_materials_samples.data_encryption_key.data_key == raw_aes_keyring_decrypted_data_key
def test_aws_kms_single_cmk_keyring_on_decrypt_fail(caplog): # In this context there are no KMS CMKs, so any calls to KMS will fail. caplog.set_level(logging.DEBUG) keyring = _AwsKmsSingleCmkKeyring(key_id="foo", client_supplier=DefaultClientSupplier()) initial_materials = DecryptionMaterials(algorithm=ALGORITHM, encryption_context={}) result_materials = keyring.on_decrypt( decryption_materials=initial_materials, encrypted_data_keys=( EncryptedDataKey( key_provider=MasterKeyInfo(provider_id=KEY_NAMESPACE, key_info=b"foo"), encrypted_data_key=b"bar" ), ), ) assert not result_materials.data_encryption_key log_data = caplog.text # This means that it did actually try to decrypt the EDK but encountered an error talking to KMS. assert "Unable to decrypt encrypted data key from" in log_data
def test_try_aws_kms_decrypt_error(caplog): # In this context there are no KMS CMKs, so any calls to KMS will fail. caplog.set_level(logging.DEBUG) encrypted_data_key = EncryptedDataKey( key_provider=MasterKeyInfo(provider_id=KEY_NAMESPACE, key_info=b"foo"), encrypted_data_key=b"bar" ) initial_decryption_materials = DecryptionMaterials(algorithm=ALGORITHM, encryption_context={},) result_materials = _try_aws_kms_decrypt( client_supplier=DefaultClientSupplier(), decryption_materials=initial_decryption_materials, grant_tokens=[], encrypted_data_key=encrypted_data_key, ) assert result_materials.data_encryption_key is None log_data = caplog.text # This means that it did actually try to decrypt the EDK but encountered an error talking to KMS. assert "Unable to decrypt encrypted data key from" in log_data
def test_aws_kms_discovery_keyring_on_decrypt(encryption_materials_for_discovery_decrypt): generator_key_id, encryption_materials = encryption_materials_for_discovery_decrypt decrypting_keyring = _AwsKmsDiscoveryKeyring(client_supplier=DefaultClientSupplier()) initial_decryption_materials = DecryptionMaterials( algorithm=encryption_materials.algorithm, encryption_context=encryption_materials.encryption_context ) result_materials = decrypting_keyring.on_decrypt( decryption_materials=initial_decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys ) assert result_materials is not initial_decryption_materials assert result_materials.data_encryption_key is not None generator_flags = _matching_flags( MasterKeyInfo(provider_id=KEY_NAMESPACE, key_info=generator_key_id), result_materials.keyring_trace ) assert KeyringTraceFlag.DECRYPTED_DATA_KEY in generator_flags assert KeyringTraceFlag.VERIFIED_ENCRYPTION_CONTEXT in generator_flags
def test_raw_rsa_encryption_decryption(encryption_materials_samples, test_raw_rsa_keyring): # Call on_encrypt function for the keyring encryption_materials = test_raw_rsa_keyring.on_encrypt(encryption_materials=encryption_materials_samples) assert encryption_materials.encrypted_data_keys is not None # Generate decryption materials decryption_materials = DecryptionMaterials( algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, verification_key=b"ex_verification_key", encryption_context=_ENCRYPTION_CONTEXT, ) # Call on_decrypt function for the keyring decryption_materials = test_raw_rsa_keyring.on_decrypt( decryption_materials=decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys ) if test_raw_rsa_keyring._private_wrapping_key is not None: # Check if the data keys match assert encryption_materials.data_encryption_key.data_key == decryption_materials.data_encryption_key.data_key
def _decrypt_materials_using_keyring(self, request): """Obtains a plaintext data key from one or more encrypted data keys using underlying keyring. :param request: decrypt materials request :type request: aws_encryption_sdk.materials_managers.DecryptionMaterialsRequest :returns: decryption materials :rtype: aws_encryption_sdk.materials_managers.DecryptionMaterials :raises InvalidCryptographicMaterialsError: if keyring cannot complete decryption materials :raises InvalidCryptographicMaterialsError: if decryption materials received from keyring do not match request """ verification_key = self._load_verification_key_from_encryption_context( algorithm=request.algorithm, encryption_context=request.encryption_context) decryption_materials = DecryptionMaterials( algorithm=request.algorithm, encryption_context=request.encryption_context.copy(), verification_key=verification_key, ) final_materials = self.keyring.on_decrypt( decryption_materials=decryption_materials, encrypted_data_keys=request.encrypted_data_keys) materials_are_valid = ( final_materials.algorithm is request.algorithm, final_materials.encryption_context == request.encryption_context, final_materials.verification_key is verification_key, ) if not all(materials_are_valid): raise InvalidCryptographicMaterialsError( "Decryption materials do not match request!") if not final_materials.is_complete: raise InvalidCryptographicMaterialsError( "Decryption materials are incomplete!") return final_materials
def test_aws_kms_single_cmk_keyring_on_decrypt_single_cmk(fake_generator): keyring = _AwsKmsSingleCmkKeyring(key_id=fake_generator, client_supplier=DefaultClientSupplier()) initial_encryption_materials = EncryptionMaterials(algorithm=ALGORITHM, encryption_context={}) encryption_materials = keyring.on_encrypt(initial_encryption_materials) initial_decryption_materials = DecryptionMaterials( algorithm=encryption_materials.algorithm, encryption_context=encryption_materials.encryption_context ) result_materials = keyring.on_decrypt( decryption_materials=initial_decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys ) assert result_materials is not initial_decryption_materials assert result_materials.data_encryption_key is not None generator_flags = _matching_flags( MasterKeyInfo(provider_id=KEY_NAMESPACE, key_info=fake_generator), result_materials.keyring_trace ) assert KeyringTraceFlag.DECRYPTED_DATA_KEY in generator_flags assert KeyringTraceFlag.VERIFIED_ENCRYPTION_CONTEXT in generator_flags
def test_decryption_materials_defaults(): test = DecryptionMaterials(data_key=MagicMock(__class__=DataKey)) assert test.verification_key is None
from aws_encryption_sdk.keyrings.base import Keyring from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials pytestmark = [pytest.mark.unit, pytest.mark.local] _encryption_materials = EncryptionMaterials( algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, encryption_context={ "encryption": "context", "values": "here" }, signing_key=b"aws-crypto-public-key", ) _decryption_materials = DecryptionMaterials( algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, verification_key=b"ex_verification_key") _encrypted_data_keys = [] def test_keyring_no_encrypt(): with pytest.raises(NotImplementedError) as exc_info: Keyring().on_encrypt(encryption_materials=_encryption_materials) assert exc_info.match("Keyring does not implement on_encrypt function") def test_keyring_no_decrypt(): with pytest.raises(NotImplementedError) as exc_info: Keyring().on_decrypt(decryption_materials=_decryption_materials, encrypted_data_keys=_encrypted_data_keys)
def get_decryption_materials_without_data_encryption_key(): return DecryptionMaterials( algorithm=AlgorithmSuite.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, verification_key=b"ex_verification_key", encryption_context=_ENCRYPTION_CONTEXT, )
def get_decryption_materials_without_data_key(): return DecryptionMaterials(encryption_context=_ENCRYPTION_CONTEXT, verification_key=b"ex_verification_key")