Beispiel #1
0
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
Beispiel #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
Beispiel #3
0
def test_try_aws_kms_decrypt_succeed(fake_generator):
    encryption_context = {"foo": "bar"}
    kms = boto3.client("kms", region_name=FAKE_REGION)
    plaintext = b"0123" * 8
    response = kms.encrypt(KeyId=fake_generator, Plaintext=plaintext, EncryptionContext=encryption_context)

    encrypted_data_key = EncryptedDataKey(
        key_provider=MasterKeyInfo(provider_id=KEY_NAMESPACE, key_info=response["KeyId"]),
        encrypted_data_key=response["CiphertextBlob"],
    )

    initial_decryption_materials = DecryptionMaterials(algorithm=ALGORITHM, encryption_context=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.data_key == plaintext

    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 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 __attrs_post_init__(self):
        # type: () -> None
        """Prepares initial values not handled by attrs."""
        key_size_to_wrapping_algorithm = {
            wrapper.algorithm.kdf_input_len: wrapper
            for wrapper in (
                WrappingAlgorithm.AES_128_GCM_IV12_TAG16_NO_PADDING,
                WrappingAlgorithm.AES_192_GCM_IV12_TAG16_NO_PADDING,
                WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING,
            )
        }

        try:
            self._wrapping_algorithm = key_size_to_wrapping_algorithm[len(
                self._wrapping_key)]
        except KeyError:
            raise ValueError(
                "Invalid wrapping key length. Must be one of {} bytes.".format(
                    sorted(key_size_to_wrapping_algorithm.keys())))

        self._key_provider = MasterKeyInfo(provider_id=self.key_namespace,
                                           key_info=self.key_name)

        self._wrapping_key_structure = WrappingKey(
            wrapping_algorithm=self._wrapping_algorithm,
            wrapping_key=self._wrapping_key,
            wrapping_key_type=EncryptionKeyType.SYMMETRIC,
        )

        self._key_info_prefix = self._get_key_info_prefix(
            key_namespace=self.key_namespace,
            key_name=self.key_name,
            wrapping_key=self._wrapping_key_structure)
def deserialize_encrypted_data_keys(stream, max_encrypted_data_keys=None):
    # type: (IO, Union[int, None]) -> Set[EncryptedDataKey]
    """Deserialize some encrypted data keys from a stream.

    :param stream: Stream from which to read encrypted data keys
    :param max_encrypted_data_keys: Maximum number of encrypted data keys to deserialize
    :return: Loaded encrypted data keys
    :rtype: set of :class:`EncryptedDataKey`
    """
    (encrypted_data_key_count, ) = unpack_values(">H", stream)
    if max_encrypted_data_keys and encrypted_data_key_count > max_encrypted_data_keys:
        raise MaxEncryptedDataKeysExceeded(encrypted_data_key_count,
                                           max_encrypted_data_keys)
    encrypted_data_keys = set([])
    for _ in range(encrypted_data_key_count):
        (key_provider_length, ) = unpack_values(">H", stream)
        (key_provider_identifier, ) = unpack_values(
            ">{}s".format(key_provider_length), stream)
        (key_provider_information_length, ) = unpack_values(">H", stream)
        (key_provider_information, ) = unpack_values(
            ">{}s".format(key_provider_information_length), stream)
        (encrypted_data_key_length, ) = unpack_values(">H", stream)
        encrypted_data_key = stream.read(encrypted_data_key_length)
        encrypted_data_keys.add(
            EncryptedDataKey(
                key_provider=MasterKeyInfo(
                    provider_id=to_str(key_provider_identifier),
                    key_info=key_provider_information),
                encrypted_data_key=encrypted_data_key,
            ))
    return encrypted_data_keys
Beispiel #8
0
    def key_provider(self):
        """Provides the MasterKeyInfo object identifying this MasterKey.

        :returns: This MasterKey's Identifying Information
        :rtype: aws_encryption_sdk.structures.MasterKeyInfo
        """
        return MasterKeyInfo(self.provider_id, self.key_id)
    def _generate_data_key(self, algorithm, encryption_context=None):
        """Generates data key and returns plaintext and ciphertext of key.

        :param algorithm: Algorithm on which to base data key
        :type algorithm: aws_encryption_sdk.identifiers.Algorithm
        :param dict encryption_context: Encryption context to pass to KMS
        :returns: Generated data key
        :rtype: aws_encryption_sdk.structures.DataKey
        """
        kms_params = {
            "KeyId": self._key_id,
            "NumberOfBytes": algorithm.kdf_input_len
        }
        if encryption_context is not None:
            kms_params["EncryptionContext"] = encryption_context
        if self.config.grant_tokens:
            kms_params["GrantTokens"] = self.config.grant_tokens
        # Catch any boto3 errors and normalize to expected EncryptKeyError
        try:
            response = self.config.client.generate_data_key(**kms_params)
            plaintext = response["Plaintext"]
            ciphertext = response["CiphertextBlob"]
            key_id = response["KeyId"]
        except (ClientError, KeyError):
            error_message = "Master Key {key_id} unable to generate data key".format(
                key_id=self._key_id)
            _LOGGER.exception(error_message)
            raise GenerateKeyError(error_message)
        return DataKey(
            key_provider=MasterKeyInfo(provider_id=self.provider_id,
                                       key_info=key_id),
            data_key=plaintext,
            encrypted_data_key=ciphertext,
        )
    def _encrypt_data_key(self, data_key, algorithm, encryption_context=None):
        """Encrypts a data key and returns the ciphertext.

        :param data_key: Unencrypted data key
        :type data_key: :class:`aws_encryption_sdk.structures.RawDataKey`
            or :class:`aws_encryption_sdk.structures.DataKey`
        :param algorithm: Placeholder to maintain API compatibility with parent
        :param dict encryption_context: Encryption context to pass to KMS
        :returns: Data key containing encrypted data key
        :rtype: aws_encryption_sdk.structures.EncryptedDataKey
        :raises EncryptKeyError: if Master Key is unable to encrypt data key
        """
        kms_params = {"KeyId": self._key_id, "Plaintext": data_key.data_key}
        if encryption_context:
            kms_params["EncryptionContext"] = encryption_context
        if self.config.grant_tokens:
            kms_params["GrantTokens"] = self.config.grant_tokens
        # Catch any boto3 errors and normalize to expected EncryptKeyError
        try:
            response = self.config.client.encrypt(**kms_params)
            ciphertext = response["CiphertextBlob"]
            key_id = response["KeyId"]
        except (ClientError, KeyError):
            error_message = "Master Key {key_id} unable to encrypt data key".format(
                key_id=self._key_id)
            _LOGGER.exception(error_message)
            raise EncryptKeyError(error_message)
        return EncryptedDataKey(key_provider=MasterKeyInfo(
            provider_id=self.provider_id, key_info=key_id),
                                encrypted_data_key=ciphertext)
Beispiel #11
0
    def test_encrypt_data_key(self, config_class, key_class, key_id):
        config = config_class(key_id=key_id, client=self.mock_client)
        test = key_class(config=config)
        self.mock_client.encrypt.return_value["KeyId"] = key_id
        # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.11
        # //= type=test
        # //# The inputs MUST be the same as the Master Key Encrypt Data Key
        # //# (../master-key-interface.md#encrypt-data-key) interface.
        encrypted_key = test._encrypt_data_key(self.mock_data_key,
                                               self.mock_algorithm)

        # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.11
        # //= type=test
        # //# The master key MUST use the configured AWS KMS client to make an AWS KMS Encrypt
        # //# (https://docs.aws.amazon.com/kms/latest/APIReference/
        # //# API_Encrypt.html) request constructed as follows:
        self.mock_client.encrypt.assert_called_once_with(
            KeyId=key_id.decode("ascii"), Plaintext=VALUES["data_key"])

        # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.11
        # //= type=test
        # //# The response's cipher text blob MUST be used as the "ciphertext" for the
        # //# encrypted data key.

        # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.11
        # //= type=test
        # //# The output MUST be the same as the Master Key Encrypt Data Key
        # //# (../master-key-interface.md#encrypt-data-key) interface.
        assert encrypted_key == EncryptedDataKey(
            key_provider=MasterKeyInfo(provider_id=test.provider_id,
                                       key_info=key_id.decode("ascii")),
            encrypted_data_key=VALUES["encrypted_data_key"],
        )
Beispiel #12
0
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 _deserialize_encrypted_data_keys(stream):
    # type: (IO) -> Set[EncryptedDataKey]
    """Deserialize some encrypted data keys from a stream.

    :param stream: Stream from which to read encrypted data keys
    :return: Loaded encrypted data keys
    :rtype: set of :class:`EncryptedDataKey`
    """
    (encrypted_data_key_count,) = unpack_values(">H", stream)
    encrypted_data_keys = set([])
    for _ in range(encrypted_data_key_count):
        (key_provider_length,) = unpack_values(">H", stream)
        (key_provider_identifier,) = unpack_values(">{}s".format(key_provider_length), stream)
        (key_provider_information_length,) = unpack_values(">H", stream)
        (key_provider_information,) = unpack_values(">{}s".format(key_provider_information_length), stream)
        (encrypted_data_key_length,) = unpack_values(">H", stream)
        encrypted_data_key = stream.read(encrypted_data_key_length)
        encrypted_data_keys.add(
            EncryptedDataKey(
                key_provider=MasterKeyInfo(
                    provider_id=to_str(key_provider_identifier), key_info=key_provider_information
                ),
                encrypted_data_key=encrypted_data_key,
            )
        )
    return encrypted_data_keys
Beispiel #14
0
def serialize_wrapped_key(key_provider, wrapping_algorithm, wrapping_key_id,
                          encrypted_wrapped_key):
    """Serializes EncryptedData into a Wrapped EncryptedDataKey.

    :param key_provider: Info for Wrapping MasterKey
    :type key_provider: aws_encryption_sdk.structure.MasterKeyInfo
    :param wrapping_algorithm: Wrapping Algorithm with which to wrap plaintext_data_key
    :type wrapping_algorithm: aws_encryption_sdk.identifiers.WrappingAlgorithm
    :param bytes wrapping_key_id: Key ID of wrapping MasterKey
    :param encrypted_wrapped_key: Encrypted data key
    :type encrypted_wrapped_key: aws_encryption_sdk.internal.structures.EncryptedData
    :returns: Wrapped EncryptedDataKey
    :rtype: aws_encryption_sdk.structure.EncryptedDataKey
    """
    if encrypted_wrapped_key.iv is None:
        key_info = wrapping_key_id
        key_ciphertext = encrypted_wrapped_key.ciphertext
    else:
        key_info = struct.pack(
            '>{key_id_len}sII{iv_len}s'.format(
                key_id_len=len(wrapping_key_id),
                iv_len=wrapping_algorithm.algorithm.iv_len),
            to_bytes(wrapping_key_id),
            len(encrypted_wrapped_key.tag) *
            8,  # Tag Length is stored in bits, not bytes
            wrapping_algorithm.algorithm.iv_len,
            encrypted_wrapped_key.iv)
        key_ciphertext = encrypted_wrapped_key.ciphertext + encrypted_wrapped_key.tag
    return EncryptedDataKey(key_provider=MasterKeyInfo(
        provider_id=key_provider.provider_id, key_info=key_info),
                            encrypted_data_key=key_ciphertext)
Beispiel #15
0
    def setUp(self):
        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_key_provider = MasterKeyInfo(
            provider_id=VALUES['provider_id'], key_info=VALUES['key_info'])
        self.mock_wrapping_algorithm = MagicMock()
        self.mock_wrapping_algorithm.algorithm = self.mock_algorithm
        # Set up encryption_context patch
        self.mock_serialize_acc_patcher = patch(
            'aws_encryption_sdk.internal.formatting.serialize.aws_encryption_sdk.internal.formatting.encryption_context'
        )
        self.mock_serialize_acc = self.mock_serialize_acc_patcher.start()
        self.mock_serialize_acc.serialize_encryption_context.return_value = VALUES[
            'serialized_encryption_context']
        # Set up crypto patch
        self.mock_crypto_patcher = patch(
            'aws_encryption_sdk.internal.formatting.serialize.aws_encryption_sdk.internal.crypto'
        )
        self.mock_crypto = self.mock_crypto_patcher.start()
        # Set up validate_frame_length patch
        self.mock_valid_frame_length_patcher = patch(
            'aws_encryption_sdk.internal.formatting.serialize.aws_encryption_sdk.internal.utils.validate_frame_length'
        )
        self.mock_valid_frame_length = self.mock_valid_frame_length_patcher.start(
        )
        # Set up mock signer
        self.mock_signer = MagicMock()
        self.mock_signer.update.return_value = None
        self.mock_signer.finalize.return_value = VALUES['signature']
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 on_encrypt(self, encryption_materials):
        # type: (EncryptionMaterials) -> EncryptionMaterials
        trace_info = MasterKeyInfo(provider_id=KEY_NAMESPACE, key_info=self._key_id)
        new_materials = encryption_materials
        try:
            if new_materials.data_encryption_key is None:
                plaintext_key, encrypted_key = _do_aws_kms_generate_data_key(
                    client_supplier=self._client_supplier,
                    key_name=self._key_id,
                    encryption_context=new_materials.encryption_context,
                    algorithm=new_materials.algorithm,
                    grant_tokens=self._grant_tokens,
                )
                new_materials = new_materials.with_data_encryption_key(
                    data_encryption_key=plaintext_key,
                    keyring_trace=KeyringTrace(wrapping_key=trace_info, flags=_GENERATE_FLAGS),
                )
            else:
                encrypted_key = _do_aws_kms_encrypt(
                    client_supplier=self._client_supplier,
                    key_name=self._key_id,
                    plaintext_data_key=new_materials.data_encryption_key,
                    encryption_context=new_materials.encryption_context,
                    grant_tokens=self._grant_tokens,
                )
        except Exception:  # pylint: disable=broad-except
            # We intentionally WANT to catch all exceptions here
            message = "Unable to generate or encrypt data key using {}".format(trace_info)
            _LOGGER.exception(message)
            raise EncryptKeyError(message)

        return new_materials.with_encrypted_data_key(
            encrypted_data_key=encrypted_key, keyring_trace=KeyringTrace(wrapping_key=trace_info, flags=_ENCRYPT_FLAGS)
        )
Beispiel #18
0
    def test_generate_data_key(self, config_class, key_class, key_id):
        # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10
        # //= type=test
        # //# The inputs MUST be the same as the Master Key Generate Data Key
        # //# (../master-key-interface.md#generate-data-key) interface.
        config = config_class(key_id=key_id, client=self.mock_client)
        test = key_class(config=config)
        generated_key = test._generate_data_key(self.mock_algorithm)
        # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10
        # //= type=test
        # //# This master key MUST use the configured AWS KMS client to make an AWS KMS
        # //# GenerateDatakey (https://docs.aws.amazon.com/kms/latest/APIReference/
        # //# API_GenerateDataKey.html) request constructed as follows:
        self.mock_client.generate_data_key.assert_called_once_with(
            KeyId=key_id.decode("ascii"), NumberOfBytes=sentinel.kdf_input_len)

        # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10
        # //= type=test
        # //# The output MUST be the same as the Master Key Generate Data Key
        # //# (../master-key-interface.md#generate-data-key) interface.

        # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10
        # //= type=test
        # //# The response's cipher text blob MUST be used as the returned as the
        # //# ciphertext for the encrypted data key in the output.

        # //= compliance/framework/aws-kms/aws-kms-mrk-aware-master-key.txt#2.10
        # //= type=test
        # //# The response's "Plaintext" MUST be the plaintext in the output.
        assert generated_key == DataKey(
            key_provider=MasterKeyInfo(provider_id=test.provider_id,
                                       key_info=VALUES["arn"]),
            data_key=VALUES["data_key"],
            encrypted_data_key=VALUES["encrypted_data_key"],
        )
Beispiel #19
0
 def _encrypt_data_key(self, data_key, algorithm, encryption_context=None):
     encrypted_data_key = self._main_key.encrypt(data_key.data_key)
     return EncryptedDataKey(
         key_provider=MasterKeyInfo(
             provider_id=self.provider_id,
             key_info=self._main_key.key_id,
         ),
         encrypted_data_key=encrypted_data_key,
     )
Beispiel #20
0
def test_generate_data_key_error_when_data_key_exists():
    with pytest.raises(TypeError) as exc_info:
        _generate_data_key(
            encryption_materials=
            get_encryption_materials_with_data_encryption_key(),
            key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID,
                                       key_info=_KEY_ID),
        )
    assert exc_info.match("Data encryption key already exists.")
Beispiel #21
0
 def test_generate_data_key(self):
     test = KMSMasterKey(config=self.mock_kms_mkc_3)
     generated_key = test._generate_data_key(self.mock_algorithm)
     self.mock_client.generate_data_key.assert_called_once_with(
         KeyId='ex_key_info', NumberOfBytes=sentinel.kdf_input_len)
     assert generated_key == DataKey(
         key_provider=MasterKeyInfo(provider_id=test.provider_id,
                                    key_info=VALUES['arn']),
         data_key=VALUES['data_key'],
         encrypted_data_key=VALUES['encrypted_data_key'])
Beispiel #22
0
 def test_key_check_valid(self):
     mock_master_key = MockMasterKey(
         key_id=VALUES['key_info'],
         mock_generated_data_key=sentinel.generated_data_key,
         mock_encrypted_data_key=sentinel.encrypted_data_key,
         mock_decrypted_data_key=sentinel.decrypted_data_key)
     mock_data_key = MagicMock()
     mock_data_key.key_provider = MasterKeyInfo(VALUES['provider_id'],
                                                VALUES['key_info'])
     mock_master_key._key_check(mock_data_key)
Beispiel #23
0
def test_generate_data_key_error_when_data_key_not_generated(patch_os_urandom):
    patch_os_urandom.side_effect = NotImplementedError
    with pytest.raises(GenerateKeyError) as exc_info:
        _generate_data_key(
            encryption_materials=
            get_encryption_materials_without_data_encryption_key(),
            key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID,
                                       key_info=_KEY_ID),
        )
    assert exc_info.match("Unable to generate data encryption key.")
Beispiel #24
0
 def _generate_data_key(self, algorithm, encryption_context=None):
     data_key, encrypted_data_key = self._main_key.generate_data_key()
     return DataKey(
         key_provider=MasterKeyInfo(
             provider_id=self.provider_id,
             key_info=self._main_key.key_id,
         ),
         data_key=data_key,
         encrypted_data_key=encrypted_data_key,
     )
Beispiel #25
0
 def test_encrypt_data_key(self):
     test = KMSMasterKey(config=self.mock_kms_mkc_3)
     encrypted_key = test._encrypt_data_key(self.mock_data_key,
                                            self.mock_algorithm)
     self.mock_client.encrypt.assert_called_once_with(
         KeyId='ex_key_info', Plaintext=VALUES['data_key'])
     assert encrypted_key == EncryptedDataKey(
         key_provider=MasterKeyInfo(provider_id=test.provider_id,
                                    key_info=VALUES['arn']),
         encrypted_data_key=VALUES['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_owns_data_key_not_owned_asymmetric_checking_symmetric(self):
     self.mock_wrapping_key.wrapping_algorithm = WrappingAlgorithm.RSA_OAEP_SHA1_MGF1
     test_master_key = RawMasterKey(
         key_id=VALUES['wrapped_keys']['raw']['key_info'],
         provider_id=VALUES['provider_id'],
         wrapping_key=self.mock_wrapping_key)
     assert not test_master_key.owns_data_key(
         data_key=DataKey(key_provider=MasterKeyInfo(
             provider_id=VALUES['provider_id'],
             key_info=VALUES['wrapped_keys']['serialized']['key_info']),
                          encrypted_data_key=VALUES['encrypted_data_key'],
                          data_key=VALUES['data_key']))
Beispiel #28
0
 def test_serialize_wrapped_key_asymmetric(self):
     test = aws_encryption_sdk.internal.formatting.serialize.serialize_wrapped_key(
         key_provider=self.mock_key_provider,
         wrapping_algorithm=self.mock_wrapping_algorithm,
         wrapping_key_id=VALUES['wrapped_keys']['raw']['key_info'],
         encrypted_wrapped_key=EncryptedData(iv=None,
                                             ciphertext=VALUES['data_128'],
                                             tag=None))
     assert test == EncryptedDataKey(key_provider=MasterKeyInfo(
         provider_id=VALUES['provider_id'],
         key_info=VALUES['wrapped_keys']['raw']['key_info']),
                                     encrypted_data_key=VALUES['data_128'])
 def test_owns_data_key_owned_symmetric(self, mock_prefix):
     self.mock_wrapping_key.wrapping_algorithm = WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING
     test_master_key = RawMasterKey(
         key_id=VALUES['wrapped_keys']['raw']['key_info'],
         provider_id=VALUES['provider_id'],
         wrapping_key=self.mock_wrapping_key)
     assert test_master_key.owns_data_key(
         data_key=DataKey(key_provider=MasterKeyInfo(
             provider_id=VALUES['provider_id'],
             key_info=VALUES['wrapped_keys']['serialized']['key_info']),
                          encrypted_data_key=VALUES['encrypted_data_key'],
                          data_key=VALUES['data_key']))
    def __attrs_post_init__(self):
        # type: () -> None
        """Prepares initial values not handled by attrs."""
        self._key_provider = MasterKeyInfo(provider_id=self.key_namespace,
                                           key_info=self.key_name)

        if self._public_wrapping_key is None and self._private_wrapping_key is None:
            raise TypeError(
                "At least one of public key or private key must be provided.")

        if self._private_wrapping_key is not None and self._public_wrapping_key is None:
            self._public_wrapping_key = self._private_wrapping_key.public_key()