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]
Example #2
0
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
Example #12
0
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
Example #13
0
    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},
            )
        ],
    )
Example #15
0
 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
Example #17
0
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']
Example #20
0
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,
Example #21
0
def test_raw_data_key_attributes_succeeds():
    RawDataKey(key_provider=MagicMock(__class__=MasterKeyInfo), data_key=b'')
Example #22
0
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