def test_get_encryption_materials(patch_for_dcmm_encrypt): encryption_context = {"a": "b"} mock_request = MagicMock(algorithm=None, encryption_context=encryption_context) cmm = build_cmm() test = cmm.get_encryption_materials(request=mock_request) cmm.master_key_provider.master_keys_for_encryption.assert_called_once_with( encryption_context=encryption_context, plaintext_rostream=mock_request.plaintext_rostream, plaintext_length=mock_request.plaintext_length, ) cmm._generate_signing_key_and_update_encryption_context.assert_called_once_with( cmm.algorithm, encryption_context) aws_encryption_sdk.materials_managers.default.prepare_data_keys.assert_called_once_with( primary_master_key=cmm.master_key_provider.master_keys_for_encryption. return_value[0], master_keys=cmm.master_key_provider.master_keys_for_encryption. return_value[1], algorithm=cmm.algorithm, encryption_context=encryption_context, ) assert isinstance(test, EncryptionMaterials) assert test.algorithm is cmm.algorithm assert test.data_encryption_key == RawDataKey.from_data_key( patch_for_dcmm_encrypt[0][0]) assert test.encrypted_data_keys == patch_for_dcmm_encrypt[0][1] assert test.encryption_context == encryption_context assert test.signing_key == patch_for_dcmm_encrypt[1]
def test_aws_kms_discovery_keyring_on_decrypt_existing_data_key(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={}, 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 _do_aws_kms_decrypt(client_supplier, key_name, encrypted_data_key, encryption_context, grant_tokens): # type: (ClientSupplierType, str, EncryptedDataKey, Dict[str, str], Iterable[str]) -> RawDataKey """Attempt to call ``kms:Decrypt`` and return the resulting plaintext data key. Any errors encountered are passed up the chain without comment. .. versionadded:: 1.5.0 """ region = _region_from_key_id(encrypted_data_key.key_provider.key_info.decode("utf-8")) client = client_supplier(region) response = client.decrypt( CiphertextBlob=encrypted_data_key.encrypted_data_key, EncryptionContext=encryption_context, GrantTokens=grant_tokens, ) response_key_id = response["KeyId"] if response_key_id != key_name: raise DecryptKeyError( "Decryption results from AWS KMS are for an unexpected key ID!" " actual '{actual}' != expected '{expected}'".format(actual=response_key_id, expected=key_name) ) return RawDataKey( key_provider=MasterKeyInfo(provider_id=KEY_NAMESPACE, key_info=response_key_id), data_key=response["Plaintext"] )
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 _generate_data_key( encryption_materials, # type: EncryptionMaterials key_provider, # type: MasterKeyInfo ): # type: (...) -> EncryptionMaterials """Generates plaintext data key for the keyring. :param EncryptionMaterials encryption_materials: Encryption materials for the keyring to modify. :param MasterKeyInfo key_provider: Information about the key in the keyring. :rtype: EncryptionMaterials :returns: Encryption materials containing a data encryption key """ # Check if encryption materials contain data encryption key if encryption_materials.data_encryption_key is not None: raise TypeError("Data encryption key already exists.") # Generate data key try: plaintext_data_key = os.urandom( encryption_materials.algorithm.kdf_input_len) except Exception: # pylint: disable=broad-except error_message = "Unable to generate data encryption key." _LOGGER.exception(error_message) raise GenerateKeyError("Unable to generate data encryption key.") # Create a keyring trace keyring_trace = KeyringTrace(wrapping_key=key_provider, flags={KeyringTraceFlag.GENERATED_DATA_KEY}) # plaintext_data_key to RawDataKey data_encryption_key = RawDataKey(key_provider=key_provider, data_key=plaintext_data_key) return encryption_materials.with_data_encryption_key( data_encryption_key=data_encryption_key, keyring_trace=keyring_trace)
def _data_key_to_raw_data_key(data_key): # type: (Union[DataKey, RawDataKey, None]) -> Union[RawDataKey, None] """Convert a :class:`DataKey` into a :class:`RawDataKey`.""" if isinstance(data_key, RawDataKey) or data_key is None: return data_key return RawDataKey.from_data_key(data_key=data_key)
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 on_decrypt(self, decryption_materials, encrypted_data_keys): # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials """Attempt to decrypt the encrypted data keys. :param DecryptionMaterials decryption_materials: Decryption materials for keyring to modify. :param encrypted_data_keys: List of encrypted data keys. :type: List[EncryptedDataKey] :returns: Decryption materials that MAY include a plaintext data key :rtype: DecryptionMaterials """ new_materials = decryption_materials if new_materials.data_encryption_key is not None: return new_materials if self._private_wrapping_key is None: return new_materials # Decrypt data key for key in encrypted_data_keys: if key.key_provider != self._key_provider: continue # Wrapped EncryptedDataKey to deserialized EncryptedData encrypted_wrapped_key = deserialize_wrapped_key( wrapping_algorithm=self._wrapping_algorithm, wrapping_key_id=self.key_name, wrapped_encrypted_key=key) try: plaintext_data_key = self._private_wrapping_key.decrypt( ciphertext=encrypted_wrapped_key.ciphertext, padding=self._wrapping_algorithm.padding) except Exception: # pylint: disable=broad-except error_message = "Raw RSA Keyring unable to decrypt data key" _LOGGER.exception(error_message) # The Raw RSA keyring MUST evaluate every encrypted data key # until it either succeeds or runs out of encrypted data keys. continue # Create a keyring trace keyring_trace = KeyringTrace( wrapping_key=self._key_provider, flags={KeyringTraceFlag.DECRYPTED_DATA_KEY}) # Update decryption materials data_encryption_key = RawDataKey(key_provider=self._key_provider, data_key=plaintext_data_key) return new_materials.with_data_encryption_key( data_encryption_key=data_encryption_key, keyring_trace=keyring_trace) return new_materials
def on_encrypt(self, encryption_materials): # type: (EncryptionMaterials) -> EncryptionMaterials if encryption_materials.data_encryption_key is None: key_provider = MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID) data_encryption_key = RawDataKey( key_provider=key_provider, data_key=os.urandom( encryption_materials.algorithm.kdf_input_len)) encryption_materials = encryption_materials.with_data_encryption_key( data_encryption_key=data_encryption_key, keyring_trace=KeyringTrace( wrapping_key=key_provider, flags={KeyringTraceFlag.GENERATED_DATA_KEY}), ) return encryption_materials
def test_decrypt_materials(mocker, patch_for_dcmm_decrypt): mock_request = MagicMock() cmm = build_cmm() test = cmm.decrypt_materials(request=mock_request) cmm.master_key_provider.decrypt_data_key_from_list.assert_called_once_with( encrypted_data_keys=mock_request.encrypted_data_keys, algorithm=mock_request.algorithm, encryption_context=mock_request.encryption_context, ) cmm._load_verification_key_from_encryption_context.assert_called_once_with( algorithm=mock_request.algorithm, encryption_context=mock_request.encryption_context) assert test.data_key == RawDataKey.from_data_key( cmm.master_key_provider.decrypt_data_key_from_list.return_value) assert test.verification_key == patch_for_dcmm_decrypt
def test_generate_data_key(self, mock_encrypt_data_key, mock_urandom, mock_key_len_check): mock_urandom.return_value = VALUES['data_key'] mock_encrypt_data_key.return_value = self.mock_encrypted_data_key test_master_key = RawMasterKey( key_id=VALUES['wrapped_keys']['raw']['key_info'], provider_id=VALUES['provider_id'], wrapping_key=self.mock_wrapping_key) test = test_master_key.generate_data_key( algorithm=self.mock_algorithm, encryption_context=VALUES['encryption_context']) mock_urandom.assert_called_once_with(sentinel.kdf_input_len) mock_encrypt_data_key.assert_called_once_with( data_key=RawDataKey(key_provider=test_master_key.key_provider, data_key=VALUES['data_key']), algorithm=self.mock_algorithm, encryption_context=VALUES['encryption_context']) assert test == self.mock_data_key
def test_do_aws_kms_encrypt(fake_generator): encryption_context = {"foo": "bar"} plaintext = b"0123" * 8 encrypted_key = _do_aws_kms_encrypt( client_supplier=DefaultClientSupplier(), key_name=fake_generator, plaintext_data_key=RawDataKey( key_provider=MasterKeyInfo(provider_id=KEY_NAMESPACE, key_info=fake_generator), data_key=plaintext ), encryption_context=encryption_context, grant_tokens=[], ) kms = boto3.client("kms", region_name=FAKE_REGION) response = kms.decrypt(CiphertextBlob=encrypted_key.encrypted_data_key, EncryptionContext=encryption_context) assert response["Plaintext"] == plaintext
def _generate_data_key(self, algorithm, encryption_context): """Generates data key and returns :class:`aws_encryption_sdk.structure.DataKey`. :param algorithm: Algorithm on which to base data key :type algorithm: aws_encryption_sdk.identifiers.Algorithm :param dict encryption_context: Encryption context to use in encryption :returns: Generated data key :rtype: aws_encryption_sdk.structure.DataKey """ plaintext_data_key = os.urandom(algorithm.kdf_input_len) encrypted_data_key = self._encrypt_data_key( data_key=RawDataKey(key_provider=self.key_provider, data_key=plaintext_data_key), algorithm=algorithm, encryption_context=encryption_context) return DataKey( key_provider=encrypted_data_key.key_provider, data_key=plaintext_data_key, encrypted_data_key=encrypted_data_key.encrypted_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_generate_data_key(self, mock_encrypt_data_key, mock_urandom, mock_key_len_check): mock_urandom.return_value = VALUES["data_key"] mock_encrypt_data_key.return_value = self.mock_encrypted_data_key test_master_key = RawMasterKey( key_id=VALUES["wrapped_keys"]["raw"]["key_info"], provider_id=VALUES["provider_id"], wrapping_key=self.mock_wrapping_key, ) test = test_master_key.generate_data_key( algorithm=self.mock_algorithm, encryption_context=VALUES["encryption_context"]) mock_urandom.assert_called_once_with(sentinel.kdf_input_len) mock_encrypt_data_key.assert_called_once_with( data_key=RawDataKey(key_provider=test_master_key.key_provider, data_key=VALUES["data_key"]), algorithm=self.mock_algorithm, encryption_context=VALUES["encryption_context"], ) assert test == self.mock_data_key
def _do_aws_kms_generate_data_key(client_supplier, key_name, encryption_context, algorithm, grant_tokens): # type: (ClientSupplierType, str, Dict[str, str], AlgorithmSuite, Iterable[str]) -> (RawDataKey, EncryptedDataKey) """Attempt to call ``kms:GenerateDataKey`` and return the resulting plaintext and encrypted data keys. Any errors encountered are passed up the chain without comment. .. versionadded:: 1.5.0 """ region = _region_from_key_id(key_name) client = client_supplier(region) response = client.generate_data_key( KeyId=key_name, NumberOfBytes=algorithm.kdf_input_len, EncryptionContext=encryption_context, GrantTokens=grant_tokens, ) provider = MasterKeyInfo(provider_id=KEY_NAMESPACE, key_info=response["KeyId"]) plaintext_key = RawDataKey(key_provider=provider, data_key=response["Plaintext"]) encrypted_key = EncryptedDataKey(key_provider=provider, encrypted_data_key=response["CiphertextBlob"]) return plaintext_key, encrypted_key
def test_aws_kms_single_cmk_keyring_on_encrypt_existing_data_key(fake_generator): keyring = _AwsKmsSingleCmkKeyring(key_id=fake_generator, client_supplier=DefaultClientSupplier()) initial_materials = EncryptionMaterials( 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_encrypt(initial_materials) assert result_materials is not 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 not in generator_flags assert KeyringTraceFlag.ENCRYPTED_DATA_KEY in generator_flags assert KeyringTraceFlag.SIGNED_ENCRYPTION_CONTEXT in generator_flags
def apply_fixtures(self): # Set up mock key provider and keys self.mock_key_provider_1 = MasterKeyInfo(provider_id="adijoasijfoi", key_info=b"asoiwef8q34") self.mock_raw_data_key_1_bytes = b"asioufhaw9eruhtg" self.mock_generated_data_key_1_bytes = b"df2hj9348r9824" self.mock_encrypted_data_key_1_bytes = b"asioufhaw9eruhtg" self.mock_raw_data_key_1 = RawDataKey( key_provider=self.mock_key_provider_1, data_key=self.mock_raw_data_key_1_bytes) self.mock_generated_data_key_1 = DataKey( key_provider=self.mock_key_provider_1, data_key=self.mock_generated_data_key_1_bytes, encrypted_data_key=self.mock_encrypted_data_key_1_bytes, ) self.mock_encrypted_data_key_1 = EncryptedDataKey( key_provider=self.mock_key_provider_1, encrypted_data_key=self.mock_encrypted_data_key_1_bytes) self.mock_key_provider_2 = MasterKeyInfo(provider_id="9heui5349gh38", key_info=b"fj98349yhsfd") self.mock_raw_data_key_2_bytes = b"ane4856ht9w87y5" self.mock_generated_data_key_2_bytes = b"fih94587ty3t58yh5tg" self.mock_encrypted_data_key_2_bytes = b"ane4856ht9w87y5" self.mock_generated_data_key_2 = DataKey( key_provider=self.mock_key_provider_2, data_key=self.mock_generated_data_key_2_bytes, encrypted_data_key=self.mock_encrypted_data_key_2_bytes, ) self.mock_encrypted_data_key_2 = EncryptedDataKey( key_provider=self.mock_key_provider_2, encrypted_data_key=self.mock_encrypted_data_key_2_bytes) self.mock_key_provider_3 = MasterKeyInfo( provider_id="sdfiwehjf9384u", key_info=b"evih5874yh587tyhu5") self.mock_raw_data_key_3_bytes = b"f839u459t83uh5rugh" self.mock_generated_data_key_3_bytes = b"sjhfuiehw498gfyu34098upoi" self.mock_encrypted_data_key_3_bytes = b"f839u459t83uh5rugh" self.mock_generated_data_key_3 = DataKey( key_provider=self.mock_key_provider_3, data_key=self.mock_generated_data_key_3_bytes, encrypted_data_key=self.mock_encrypted_data_key_3_bytes, ) self.mock_encrypted_data_key_3 = EncryptedDataKey( key_provider=self.mock_key_provider_3, encrypted_data_key=self.mock_encrypted_data_key_3_bytes) self.mock_master_key_provider = MagicMock() self.mock_master_key_1 = MagicMock() self.mock_master_key_1.encrypt_data_key.return_value = self.mock_encrypted_data_key_1 self.mock_master_key_1.generate_data_key.return_value = self.mock_generated_data_key_1 self.mock_master_key_2 = MagicMock() self.mock_master_key_2.encrypt_data_key.return_value = self.mock_encrypted_data_key_2 self.mock_master_key_2.generate_data_key.return_value = self.mock_generated_data_key_2 self.mock_master_key_3 = MagicMock() self.mock_master_key_3.encrypt_data_key.return_value = self.mock_encrypted_data_key_3 self.mock_master_key_3.generate_data_key.return_value = self.mock_generated_data_key_3 self.mock_master_key_provider.master_keys_for_encryption.return_value = ( self.mock_master_key_1, [ self.mock_master_key_1, self.mock_master_key_2, self.mock_master_key_3 ], ) self.mock_decrypted_data_key_bytes = b"sehf98w34y987y9uierfh" self.mock_encrypted_data_key_bytes = b"sdhf4w398hfwea98ihfr0w8" self.mock_data_key = DataKey( key_provider=self.mock_key_provider_1, data_key=self.mock_decrypted_data_key_bytes, encrypted_data_key=self.mock_encrypted_data_key_bytes, ) self.mock_encrypted_data_key = EncryptedDataKey( key_provider=self.mock_key_provider_1, encrypted_data_key=self.mock_encrypted_data_key_bytes) self.mock_decrypted_data_key = DataKey( key_provider=self.mock_key_provider_1, data_key=self.mock_decrypted_data_key_bytes, encrypted_data_key=self.mock_encrypted_data_key_1_bytes, ) self.mock_master_key_provider.decrypt_data_key.return_value = self.mock_decrypted_data_key # Set up mock algorithm self.mock_algorithm = MagicMock() self.mock_algorithm.encryption_algorithm.block_size = VALUES[ "block_size"] self.mock_algorithm.algorithm_id = VALUES["algorithm_id"] self.mock_algorithm.iv_len = VALUES["iv_len"] self.mock_algorithm.tag_len = self.mock_algorithm.auth_len = VALUES[ "tag_len"] self.mock_algorithm.data_key_len = VALUES["data_key_len"] # Set up mock objects self.mock_bad_encrypted_key = MagicMock() self.mock_bad_encrypted_key.encrypted_data_key = sentinel.bad_encrypted_data_key self.mock_aws_encryption_sdk = MagicMock() # Set up os.urandom patch self.mock_urandom_patcher = patch( "aws_encryption_sdk.internal.utils.os.urandom") self.mock_urandom = self.mock_urandom_patcher.start() self.mock_urandom.return_value = sentinel.random # Set up KMSClient patch self.mock_aws_encryption_sdk_instance = MagicMock() self.mock_aws_encryption_sdk_instance.generate_data_key.return_value = ( VALUES["data_key"], VALUES["encrypted_data_key"], ) self.mock_aws_encryption_sdk_instance.decrypt.return_value = VALUES[ "data_key"] self.mock_aws_encryption_sdk_instance.encrypt.return_value = VALUES[ "encrypted_data_key"] yield # Run tearDown self.mock_urandom_patcher.stop()
def setUp(self): # Set up mock key provider and keys self.mock_key_provider_1 = MasterKeyInfo(provider_id='adijoasijfoi', key_info=b'asoiwef8q34') self.mock_raw_data_key_1_bytes = b'asioufhaw9eruhtg' self.mock_generated_data_key_1_bytes = b'df2hj9348r9824' self.mock_encrypted_data_key_1_bytes = b'asioufhaw9eruhtg' self.mock_raw_data_key_1 = RawDataKey( key_provider=self.mock_key_provider_1, data_key=self.mock_raw_data_key_1_bytes) self.mock_generated_data_key_1 = DataKey( key_provider=self.mock_key_provider_1, data_key=self.mock_generated_data_key_1_bytes, encrypted_data_key=self.mock_encrypted_data_key_1_bytes) self.mock_encrypted_data_key_1 = EncryptedDataKey( key_provider=self.mock_key_provider_1, encrypted_data_key=self.mock_encrypted_data_key_1_bytes) self.mock_key_provider_2 = MasterKeyInfo(provider_id='9heui5349gh38', key_info=b'fj98349yhsfd') self.mock_raw_data_key_2_bytes = b'ane4856ht9w87y5' self.mock_generated_data_key_2_bytes = b'fih94587ty3t58yh5tg' self.mock_encrypted_data_key_2_bytes = b'ane4856ht9w87y5' self.mock_generated_data_key_2 = DataKey( key_provider=self.mock_key_provider_2, data_key=self.mock_generated_data_key_2_bytes, encrypted_data_key=self.mock_encrypted_data_key_2_bytes) self.mock_encrypted_data_key_2 = EncryptedDataKey( key_provider=self.mock_key_provider_2, encrypted_data_key=self.mock_encrypted_data_key_2_bytes) self.mock_key_provider_3 = MasterKeyInfo( provider_id='sdfiwehjf9384u', key_info=b'evih5874yh587tyhu5') self.mock_raw_data_key_3_bytes = b'f839u459t83uh5rugh' self.mock_generated_data_key_3_bytes = b'sjhfuiehw498gfyu34098upoi' self.mock_encrypted_data_key_3_bytes = b'f839u459t83uh5rugh' self.mock_generated_data_key_3 = DataKey( key_provider=self.mock_key_provider_3, data_key=self.mock_generated_data_key_3_bytes, encrypted_data_key=self.mock_encrypted_data_key_3_bytes) self.mock_encrypted_data_key_3 = EncryptedDataKey( key_provider=self.mock_key_provider_3, encrypted_data_key=self.mock_encrypted_data_key_3_bytes) self.mock_master_key_provider = MagicMock() self.mock_master_key_1 = MagicMock() self.mock_master_key_1.encrypt_data_key.return_value = self.mock_encrypted_data_key_1 self.mock_master_key_1.generate_data_key.return_value = self.mock_generated_data_key_1 self.mock_master_key_2 = MagicMock() self.mock_master_key_2.encrypt_data_key.return_value = self.mock_encrypted_data_key_2 self.mock_master_key_2.generate_data_key.return_value = self.mock_generated_data_key_2 self.mock_master_key_3 = MagicMock() self.mock_master_key_3.encrypt_data_key.return_value = self.mock_encrypted_data_key_3 self.mock_master_key_3.generate_data_key.return_value = self.mock_generated_data_key_3 self.mock_master_key_provider.master_keys_for_encryption.return_value = ( self.mock_master_key_1, [ self.mock_master_key_1, self.mock_master_key_2, self.mock_master_key_3 ]) self.mock_decrypted_data_key_bytes = b'sehf98w34y987y9uierfh' self.mock_encrypted_data_key_bytes = b'sdhf4w398hfwea98ihfr0w8' self.mock_data_key = DataKey( key_provider=self.mock_key_provider_1, data_key=self.mock_decrypted_data_key_bytes, encrypted_data_key=self.mock_encrypted_data_key_bytes) self.mock_encrypted_data_key = EncryptedDataKey( key_provider=self.mock_key_provider_1, encrypted_data_key=self.mock_encrypted_data_key_bytes) self.mock_decrypted_data_key = DataKey( key_provider=self.mock_key_provider_1, data_key=self.mock_decrypted_data_key_bytes, encrypted_data_key=self.mock_encrypted_data_key_1_bytes) self.mock_master_key_provider.decrypt_data_key.return_value = self.mock_decrypted_data_key # Set up mock algorithm self.mock_algorithm = MagicMock() self.mock_algorithm.encryption_algorithm.block_size = VALUES[ 'block_size'] self.mock_algorithm.algorithm_id = VALUES['algorithm_id'] self.mock_algorithm.iv_len = VALUES['iv_len'] self.mock_algorithm.tag_len = self.mock_algorithm.auth_len = VALUES[ 'tag_len'] self.mock_algorithm.data_key_len = VALUES['data_key_len'] # Set up mock objects self.mock_bad_encrypted_key = MagicMock() self.mock_bad_encrypted_key.encrypted_data_key = sentinel.bad_encrypted_data_key self.mock_aws_encryption_sdk = MagicMock() # Set up os.urandom patch self.mock_urandom_patcher = patch( 'aws_encryption_sdk.internal.utils.os.urandom') self.mock_urandom = self.mock_urandom_patcher.start() self.mock_urandom.return_value = sentinel.random # Set up KMSClient patch self.mock_aws_encryption_sdk_instance = MagicMock() self.mock_aws_encryption_sdk_instance.generate_data_key.return_value = ( VALUES['data_key'], VALUES['encrypted_data_key']) self.mock_aws_encryption_sdk_instance.decrypt.return_value = VALUES[ 'data_key'] self.mock_aws_encryption_sdk_instance.encrypt.return_value = VALUES[ 'encrypted_data_key']
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}, ) ], ) _MULTI_KEYRING_WITH_GENERATOR_AND_CHILDREN = MultiKeyring( generator=RawAESKeyring( key_namespace=_PROVIDER_ID,
def test_raw_data_key_attributes_succeeds(): RawDataKey(key_provider=MagicMock(__class__=MasterKeyInfo), data_key=b'')
def test_raw_data_key_attributes_fails(key_provider, data_key): with pytest.raises(TypeError): RawDataKey(key_provider=key_provider, data_key=data_key)
def on_decrypt(self, decryption_materials, encrypted_data_keys): # type: (DecryptionMaterials, Iterable[EncryptedDataKey]) -> DecryptionMaterials """Attempt to decrypt the encrypted data keys. :param DecryptionMaterials decryption_materials: Decryption materials for the keyring to modify :param List[EncryptedDataKey] encrypted_data_keys: List of encrypted data keys :returns: Decryption materials that MAY include a plaintext data key :rtype: DecryptionMaterials """ new_materials = decryption_materials if new_materials.data_encryption_key is not None: return new_materials # Decrypt data key expected_key_info_len = len( self._key_info_prefix) + self._wrapping_algorithm.algorithm.iv_len for key in encrypted_data_keys: if (key.key_provider.provider_id != self._key_provider.provider_id or len(key.key_provider.key_info) != expected_key_info_len or not key.key_provider.key_info.startswith( self._key_info_prefix)): continue # Wrapped EncryptedDataKey to deserialized EncryptedData encrypted_wrapped_key = deserialize_wrapped_key( wrapping_algorithm=self._wrapping_algorithm, wrapping_key_id=self.key_name, wrapped_encrypted_key=key) # EncryptedData to raw key string try: plaintext_data_key = self._wrapping_key_structure.decrypt( encrypted_wrapped_data_key=encrypted_wrapped_key, encryption_context=new_materials.encryption_context, ) except Exception: # pylint: disable=broad-except # We intentionally WANT to catch all exceptions here error_message = "Raw AES Keyring unable to decrypt data key" _LOGGER.exception(error_message) # The Raw AES keyring MUST evaluate every encrypted data key # until it either succeeds or runs out of encrypted data keys. continue # Create a keyring trace keyring_trace = KeyringTrace( wrapping_key=self._key_provider, flags={ KeyringTraceFlag.DECRYPTED_DATA_KEY, KeyringTraceFlag.VERIFIED_ENCRYPTION_CONTEXT }, ) # Update decryption materials data_encryption_key = RawDataKey(key_provider=self._key_provider, data_key=plaintext_data_key) return new_materials.with_data_encryption_key( data_encryption_key=data_encryption_key, keyring_trace=keyring_trace) return new_materials