def sample_encryption_materials(): return [ EncryptionMaterials( algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, encryption_context=_ENCRYPTION_CONTEXT, signing_key=_SIGNING_KEY, ), EncryptionMaterials( algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, data_encryption_key=RawDataKey( key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), data_key= b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', ), encryption_context=_ENCRYPTION_CONTEXT, signing_key=_SIGNING_KEY, keyring_trace=[ KeyringTrace( wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), flags={KeyringTraceFlag.GENERATED_DATA_KEY}, ) ], ), ]
def get_encryption_materials_with_encrypted_data_key(): return EncryptionMaterials( 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(', ), encrypted_data_keys=[ EncryptedDataKey( key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_EXISTING_KEY_ID), encrypted_data_key= b"\xde^\x97\x7f\x84\xe9\x9e\x98\xd0\xe2\xf8\xd5\xcb\xe9\x7f.}\x87\x16,\x11n#\xc8p" b"\xdb\xbf\x94\x86*Q\x06\xd2\xf5\xdah\x08\xa4p\x81\xf7\xf4G\x07FzE\xde", ) ], encryption_context=_ENCRYPTION_CONTEXT, signing_key=_SIGNING_KEY, keyring_trace=[ KeyringTrace( wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_EXISTING_KEY_ID), flags={ KeyringTraceFlag.GENERATED_DATA_KEY, KeyringTraceFlag.ENCRYPTED_DATA_KEY }, ) ], )
def test_encryption_materials_defaults(): test = EncryptionMaterials( algorithm=MagicMock(__class__=Algorithm), data_encryption_key=MagicMock(__class__=DataKey), encrypted_data_keys=set([]), encryption_context={}) assert test.signing_key is None
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_generate_data_key_keyring_trace(): encryption_materials_without_data_key = EncryptionMaterials( algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, encryption_context=_ENCRYPTION_CONTEXT, signing_key=_SIGNING_KEY, ) key_provider_info = MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID) new_materials = _generate_data_key( encryption_materials=encryption_materials_without_data_key, key_provider=key_provider_info, ) assert new_materials is not encryption_materials_without_data_key assert encryption_materials_without_data_key.data_encryption_key is None assert not encryption_materials_without_data_key.keyring_trace assert new_materials.data_encryption_key is not None assert new_materials.data_encryption_key.key_provider == key_provider_info trace_entries = [ entry for entry in new_materials.keyring_trace if entry.wrapping_key == key_provider_info ] assert len(trace_entries) == 1 generate_traces = [ entry for entry in trace_entries if entry.flags == {KeyringTraceFlag.GENERATED_DATA_KEY} ] assert len(generate_traces) == 1
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_aws_kms_discovery_keyring_on_encrypt(): keyring = _AwsKmsDiscoveryKeyring(client_supplier=DefaultClientSupplier()) initial_materials = EncryptionMaterials(algorithm=ALGORITHM, encryption_context={}) result_materials = keyring.on_encrypt(initial_materials) assert result_materials is initial_materials assert len(result_materials.encrypted_data_keys) == 0
def test_aws_kms_single_cmk_keyring_on_encrypt_fail(): # In this context there are no KMS CMKs, so any calls to KMS will fail. keyring = _AwsKmsSingleCmkKeyring(key_id="foo", client_supplier=DefaultClientSupplier()) initial_materials = EncryptionMaterials(algorithm=ALGORITHM, encryption_context={}) with pytest.raises(EncryptKeyError) as excinfo: keyring.on_encrypt(initial_materials) excinfo.match(r"Unable to generate or encrypt data key using *")
def on_encrypt(self, encryption_materials): # type: (EncryptionMaterials) -> EncryptionMaterials materials = self._inner_keyring.on_encrypt(encryption_materials) return EncryptionMaterials( algorithm=materials.algorithm, data_encryption_key=materials.data_encryption_key, encryption_context=materials.encryption_context, signing_key=materials.signing_key, keyring_trace=materials.keyring_trace, )
def _break_encryption_materials(self, encryption_materials): # type: (EncryptionMaterials) -> EncryptionMaterials return EncryptionMaterials( algorithm=self._broken_algorithm(encryption_materials.algorithm), data_encryption_key=encryption_materials.data_encryption_key, encrypted_data_keys=encryption_materials.encrypted_data_keys, encryption_context=self._broken_encryption_context( encryption_materials.encryption_context), signing_key=self._broken_key(encryption_materials.signing_key), keyring_trace=encryption_materials.keyring_trace, )
def test_private_key_cannot_encrypt(): 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) with pytest.raises(EncryptKeyError) as excinfo: test_keyring.on_encrypt(initial_materials) excinfo.match("A public key is required to encrypt")
def test_aws_kms_single_cmk_keyring_on_encrypt_empty_materials(fake_generator): keyring = _AwsKmsSingleCmkKeyring(key_id=fake_generator, client_supplier=DefaultClientSupplier()) initial_materials = EncryptionMaterials(algorithm=ALGORITHM, encryption_context={}) result_materials = keyring.on_encrypt(initial_materials) assert result_materials.data_encryption_key is not None assert len(result_materials.encrypted_data_keys) == 1 generator_flags = _matching_flags( MasterKeyInfo(provider_id=KEY_NAMESPACE, key_info=fake_generator), result_materials.keyring_trace ) assert KeyringTraceFlag.GENERATED_DATA_KEY in generator_flags assert KeyringTraceFlag.ENCRYPTED_DATA_KEY in generator_flags assert KeyringTraceFlag.SIGNED_ENCRYPTION_CONTEXT in generator_flags
def _get_encryption_materials_using_master_key_provider(self, request): """Creates encryption materials using underlying master key provider. :param request: encryption materials request :type request: aws_encryption_sdk.materials_managers.EncryptionMaterialsRequest :returns: encryption materials :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials :raises MasterKeyProviderError: if no master keys are available from the underlying master key provider :raises MasterKeyProviderError: if the primary master key provided by the underlying master key provider is not included in the full set of master keys provided by that provider """ algorithm = request.algorithm if request.algorithm is not None else self.algorithm encryption_context = request.encryption_context.copy() signing_key = self._generate_signing_key_and_update_encryption_context( algorithm, encryption_context) primary_master_key, master_keys = self.master_key_provider.master_keys_for_encryption( encryption_context=encryption_context, plaintext_rostream=request.plaintext_rostream, plaintext_length=request.plaintext_length, ) if not master_keys: raise MasterKeyProviderError( "No Master Keys available from Master Key Provider") if primary_master_key not in master_keys: raise MasterKeyProviderError( "Primary Master Key not in provided Master Keys") data_encryption_key, encrypted_data_keys = prepare_data_keys( primary_master_key=primary_master_key, master_keys=master_keys, algorithm=algorithm, encryption_context=encryption_context, ) _LOGGER.debug("Post-encrypt encryption context: %s", encryption_context) return EncryptionMaterials( algorithm=algorithm, data_encryption_key=data_encryption_key, encrypted_data_keys=encrypted_data_keys, encryption_context=encryption_context, signing_key=signing_key, )
def _get_encryption_materials_using_keyring(self, request): """Creates encryption materials using underlying keyring. :param request: encryption materials request :type request: aws_encryption_sdk.materials_managers.EncryptionMaterialsRequest :returns: encryption materials :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials :raises InvalidCryptographicMaterialsError: if keyring cannot complete encryption materials :raises InvalidCryptographicMaterialsError: if encryption materials received from keyring do not match request """ algorithm = request.algorithm if request.algorithm is not None else self.algorithm encryption_context = request.encryption_context.copy() signing_key = self._generate_signing_key_and_update_encryption_context( algorithm, encryption_context) expected_encryption_context = encryption_context.copy() encryption_materials = EncryptionMaterials( algorithm=algorithm, encryption_context=encryption_context, signing_key=signing_key, ) final_materials = self.keyring.on_encrypt( encryption_materials=encryption_materials) materials_are_valid = ( final_materials.algorithm is algorithm, final_materials.encryption_context == expected_encryption_context, final_materials.signing_key is signing_key, ) if not all(materials_are_valid): raise InvalidCryptographicMaterialsError( "Encryption materials do not match request!") if not final_materials.is_complete: raise InvalidCryptographicMaterialsError( "Encryption materials are incomplete!") _LOGGER.debug("Post-encrypt encryption context: %s", encryption_context) return final_materials
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_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 get_encryption_materials_without_data_encryption_key(): return EncryptionMaterials( algorithm=AlgorithmSuite.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, encryption_context=_ENCRYPTION_CONTEXT, signing_key=_SIGNING_KEY, )
from aws_encryption_sdk.identifiers import KeyringTraceFlag, WrappingAlgorithm from aws_encryption_sdk.internal.defaults import ALGORITHM from aws_encryption_sdk.keyrings.multi import MultiKeyring from aws_encryption_sdk.keyrings.raw import RawAESKeyring, RawRSAKeyring from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials from aws_encryption_sdk.structures import KeyringTrace, MasterKeyInfo, RawDataKey pytestmark = [pytest.mark.functional, pytest.mark.local] _ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"} _PROVIDER_ID = "Random Raw Keys" _KEY_ID = b"5325b043-5843-4629-869c-64794af77ada" _WRAPPING_KEY_AES = b"\xeby-\x80A6\x15rA8\x83#,\xe4\xab\xac`\xaf\x99Z\xc1\xce\xdb\xb6\x0f\xb7\x805\xb2\x14J3" _ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY = EncryptionMaterials( algorithm=ALGORITHM, encryption_context=_ENCRYPTION_CONTEXT) _ENCRYPTION_MATERIALS_WITH_DATA_KEY = EncryptionMaterials( algorithm=ALGORITHM, data_encryption_key=RawDataKey( key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), data_key= b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(', ), encryption_context=_ENCRYPTION_CONTEXT, keyring_trace=[ KeyringTrace( wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID), flags={KeyringTraceFlag.GENERATED_DATA_KEY}, )
# ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. """Unit tests for base keyring.""" import pytest from aws_encryption_sdk.identifiers import Algorithm from aws_encryption_sdk.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 encryption_materials_for_discovery_decrypt(fake_generator): encrypting_keyring = _AwsKmsSingleCmkKeyring(key_id=fake_generator, client_supplier=DefaultClientSupplier()) initial_encryption_materials = EncryptionMaterials(algorithm=ALGORITHM, encryption_context={}) return fake_generator, encrypting_keyring.on_encrypt(initial_encryption_materials)