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
                },
            )
        ],
    )
Exemple #3
0
def test_encryption_materials_defaults():
    test = EncryptionMaterials(
        algorithm=MagicMock(__class__=Algorithm),
        data_encryption_key=MagicMock(__class__=DataKey),
        encrypted_data_keys=set([]),
        encryption_context={})
    assert test.signing_key is None
Exemple #4
0
def test_private_key_can_decrypt():
    complete_keyring = RawRSAKeyring(
        key_namespace=_PROVIDER_ID,
        key_name=_KEY_ID,
        wrapping_algorithm=_WRAPPING_ALGORITHM,
        private_wrapping_key=_PRIVATE_WRAPPING_KEY,
        public_wrapping_key=_PUBLIC_WRAPPING_KEY,
    )
    test_keyring = RawRSAKeyring(
        key_namespace=_PROVIDER_ID,
        key_name=_KEY_ID,
        wrapping_algorithm=_WRAPPING_ALGORITHM,
        private_wrapping_key=_PRIVATE_WRAPPING_KEY,
    )
    initial_materials = EncryptionMaterials(
        algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384,
        encryption_context=_ENCRYPTION_CONTEXT)

    encryption_materials = complete_keyring.on_encrypt(initial_materials)

    initial_decryption_materials = DecryptionMaterials(
        algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384,
        encryption_context=_ENCRYPTION_CONTEXT)

    test_materials = test_keyring.on_decrypt(
        decryption_materials=initial_decryption_materials,
        encrypted_data_keys=encryption_materials.encrypted_data_keys)

    assert test_materials is not initial_decryption_materials
    assert test_materials.data_encryption_key is not None
Exemple #5
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
Exemple #6
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
Exemple #7
0
def test_aws_kms_discovery_keyring_on_encrypt():
    keyring = _AwsKmsDiscoveryKeyring(client_supplier=DefaultClientSupplier())

    initial_materials = EncryptionMaterials(algorithm=ALGORITHM, encryption_context={})

    result_materials = keyring.on_encrypt(initial_materials)

    assert result_materials is initial_materials
    assert len(result_materials.encrypted_data_keys) == 0
Exemple #8
0
def test_aws_kms_single_cmk_keyring_on_encrypt_fail():
    # In this context there are no KMS CMKs, so any calls to KMS will fail.
    keyring = _AwsKmsSingleCmkKeyring(key_id="foo", client_supplier=DefaultClientSupplier())

    initial_materials = EncryptionMaterials(algorithm=ALGORITHM, encryption_context={})

    with pytest.raises(EncryptKeyError) as excinfo:
        keyring.on_encrypt(initial_materials)

    excinfo.match(r"Unable to generate or encrypt data key using *")
 def on_encrypt(self, encryption_materials):
     # type: (EncryptionMaterials) -> EncryptionMaterials
     materials = self._inner_keyring.on_encrypt(encryption_materials)
     return EncryptionMaterials(
         algorithm=materials.algorithm,
         data_encryption_key=materials.data_encryption_key,
         encryption_context=materials.encryption_context,
         signing_key=materials.signing_key,
         keyring_trace=materials.keyring_trace,
     )
 def _break_encryption_materials(self, encryption_materials):
     # type: (EncryptionMaterials) -> EncryptionMaterials
     return EncryptionMaterials(
         algorithm=self._broken_algorithm(encryption_materials.algorithm),
         data_encryption_key=encryption_materials.data_encryption_key,
         encrypted_data_keys=encryption_materials.encrypted_data_keys,
         encryption_context=self._broken_encryption_context(
             encryption_materials.encryption_context),
         signing_key=self._broken_key(encryption_materials.signing_key),
         keyring_trace=encryption_materials.keyring_trace,
     )
Exemple #11
0
def test_private_key_cannot_encrypt():
    test_keyring = RawRSAKeyring(
        key_namespace=_PROVIDER_ID,
        key_name=_KEY_ID,
        wrapping_algorithm=_WRAPPING_ALGORITHM,
        private_wrapping_key=_PRIVATE_WRAPPING_KEY,
    )
    initial_materials = EncryptionMaterials(
        algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384,
        encryption_context=_ENCRYPTION_CONTEXT)

    with pytest.raises(EncryptKeyError) as excinfo:
        test_keyring.on_encrypt(initial_materials)

    excinfo.match("A public key is required to encrypt")
Exemple #12
0
def test_aws_kms_single_cmk_keyring_on_encrypt_empty_materials(fake_generator):
    keyring = _AwsKmsSingleCmkKeyring(key_id=fake_generator, client_supplier=DefaultClientSupplier())

    initial_materials = EncryptionMaterials(algorithm=ALGORITHM, encryption_context={})

    result_materials = keyring.on_encrypt(initial_materials)

    assert result_materials.data_encryption_key is not None
    assert len(result_materials.encrypted_data_keys) == 1

    generator_flags = _matching_flags(
        MasterKeyInfo(provider_id=KEY_NAMESPACE, key_info=fake_generator), result_materials.keyring_trace
    )

    assert KeyringTraceFlag.GENERATED_DATA_KEY in generator_flags
    assert KeyringTraceFlag.ENCRYPTED_DATA_KEY in generator_flags
    assert KeyringTraceFlag.SIGNED_ENCRYPTION_CONTEXT in generator_flags
    def _get_encryption_materials_using_master_key_provider(self, request):
        """Creates encryption materials using underlying master key provider.

        :param request: encryption materials request
        :type request: aws_encryption_sdk.materials_managers.EncryptionMaterialsRequest
        :returns: encryption materials
        :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials
        :raises MasterKeyProviderError: if no master keys are available from the underlying master key provider
        :raises MasterKeyProviderError: if the primary master key provided by the underlying master key provider
            is not included in the full set of master keys provided by that provider
        """
        algorithm = request.algorithm if request.algorithm is not None else self.algorithm
        encryption_context = request.encryption_context.copy()

        signing_key = self._generate_signing_key_and_update_encryption_context(
            algorithm, encryption_context)

        primary_master_key, master_keys = self.master_key_provider.master_keys_for_encryption(
            encryption_context=encryption_context,
            plaintext_rostream=request.plaintext_rostream,
            plaintext_length=request.plaintext_length,
        )
        if not master_keys:
            raise MasterKeyProviderError(
                "No Master Keys available from Master Key Provider")
        if primary_master_key not in master_keys:
            raise MasterKeyProviderError(
                "Primary Master Key not in provided Master Keys")

        data_encryption_key, encrypted_data_keys = prepare_data_keys(
            primary_master_key=primary_master_key,
            master_keys=master_keys,
            algorithm=algorithm,
            encryption_context=encryption_context,
        )

        _LOGGER.debug("Post-encrypt encryption context: %s",
                      encryption_context)

        return EncryptionMaterials(
            algorithm=algorithm,
            data_encryption_key=data_encryption_key,
            encrypted_data_keys=encrypted_data_keys,
            encryption_context=encryption_context,
            signing_key=signing_key,
        )
    def _get_encryption_materials_using_keyring(self, request):
        """Creates encryption materials using underlying keyring.

        :param request: encryption materials request
        :type request: aws_encryption_sdk.materials_managers.EncryptionMaterialsRequest
        :returns: encryption materials
        :rtype: aws_encryption_sdk.materials_managers.EncryptionMaterials
        :raises InvalidCryptographicMaterialsError: if keyring cannot complete encryption materials
        :raises InvalidCryptographicMaterialsError:
           if encryption materials received from keyring do not match request
        """
        algorithm = request.algorithm if request.algorithm is not None else self.algorithm
        encryption_context = request.encryption_context.copy()

        signing_key = self._generate_signing_key_and_update_encryption_context(
            algorithm, encryption_context)

        expected_encryption_context = encryption_context.copy()

        encryption_materials = EncryptionMaterials(
            algorithm=algorithm,
            encryption_context=encryption_context,
            signing_key=signing_key,
        )

        final_materials = self.keyring.on_encrypt(
            encryption_materials=encryption_materials)

        materials_are_valid = (
            final_materials.algorithm is algorithm,
            final_materials.encryption_context == expected_encryption_context,
            final_materials.signing_key is signing_key,
        )
        if not all(materials_are_valid):
            raise InvalidCryptographicMaterialsError(
                "Encryption materials do not match request!")

        if not final_materials.is_complete:
            raise InvalidCryptographicMaterialsError(
                "Encryption materials are incomplete!")

        _LOGGER.debug("Post-encrypt encryption context: %s",
                      encryption_context)

        return final_materials
Exemple #15
0
def test_aws_kms_single_cmk_keyring_on_decrypt_no_match(fake_generator_and_child):
    generator, child = fake_generator_and_child

    encrypting_keyring = _AwsKmsSingleCmkKeyring(key_id=generator, client_supplier=DefaultClientSupplier())
    decrypting_keyring = _AwsKmsSingleCmkKeyring(key_id=child, client_supplier=DefaultClientSupplier())

    initial_encryption_materials = EncryptionMaterials(algorithm=ALGORITHM, encryption_context={})

    encryption_materials = encrypting_keyring.on_encrypt(initial_encryption_materials)

    initial_decryption_materials = DecryptionMaterials(
        algorithm=encryption_materials.algorithm, encryption_context=encryption_materials.encryption_context
    )

    result_materials = decrypting_keyring.on_decrypt(
        decryption_materials=initial_decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys
    )

    assert result_materials.data_encryption_key is None
Exemple #16
0
def test_aws_kms_single_cmk_keyring_on_decrypt_single_cmk(fake_generator):
    keyring = _AwsKmsSingleCmkKeyring(key_id=fake_generator, client_supplier=DefaultClientSupplier())

    initial_encryption_materials = EncryptionMaterials(algorithm=ALGORITHM, encryption_context={})

    encryption_materials = keyring.on_encrypt(initial_encryption_materials)

    initial_decryption_materials = DecryptionMaterials(
        algorithm=encryption_materials.algorithm, encryption_context=encryption_materials.encryption_context
    )

    result_materials = keyring.on_decrypt(
        decryption_materials=initial_decryption_materials, encrypted_data_keys=encryption_materials.encrypted_data_keys
    )

    assert result_materials is not initial_decryption_materials
    assert result_materials.data_encryption_key is not None

    generator_flags = _matching_flags(
        MasterKeyInfo(provider_id=KEY_NAMESPACE, key_info=fake_generator), result_materials.keyring_trace
    )

    assert KeyringTraceFlag.DECRYPTED_DATA_KEY in generator_flags
    assert KeyringTraceFlag.VERIFIED_ENCRYPTION_CONTEXT in generator_flags
def get_encryption_materials_without_data_encryption_key():
    return EncryptionMaterials(
        algorithm=AlgorithmSuite.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384,
        encryption_context=_ENCRYPTION_CONTEXT,
        signing_key=_SIGNING_KEY,
    )
Exemple #18
0
from aws_encryption_sdk.identifiers import KeyringTraceFlag, WrappingAlgorithm
from aws_encryption_sdk.internal.defaults import ALGORITHM
from aws_encryption_sdk.keyrings.multi import MultiKeyring
from aws_encryption_sdk.keyrings.raw import RawAESKeyring, RawRSAKeyring
from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials
from aws_encryption_sdk.structures import KeyringTrace, MasterKeyInfo, RawDataKey

pytestmark = [pytest.mark.functional, pytest.mark.local]

_ENCRYPTION_CONTEXT = {"encryption": "context", "values": "here"}
_PROVIDER_ID = "Random Raw Keys"
_KEY_ID = b"5325b043-5843-4629-869c-64794af77ada"
_WRAPPING_KEY_AES = b"\xeby-\x80A6\x15rA8\x83#,\xe4\xab\xac`\xaf\x99Z\xc1\xce\xdb\xb6\x0f\xb7\x805\xb2\x14J3"

_ENCRYPTION_MATERIALS_WITHOUT_DATA_KEY = EncryptionMaterials(
    algorithm=ALGORITHM, encryption_context=_ENCRYPTION_CONTEXT)

_ENCRYPTION_MATERIALS_WITH_DATA_KEY = EncryptionMaterials(
    algorithm=ALGORITHM,
    data_encryption_key=RawDataKey(
        key_provider=MasterKeyInfo(provider_id=_PROVIDER_ID, key_info=_KEY_ID),
        data_key=
        b'*!\xa1"^-(\xf3\x105\x05i@B\xc2\xa2\xb7\xdd\xd5\xd5\xa9\xddm\xfae\xa8\\$\xf9d\x1e(',
    ),
    encryption_context=_ENCRYPTION_CONTEXT,
    keyring_trace=[
        KeyringTrace(
            wrapping_key=MasterKeyInfo(provider_id=_PROVIDER_ID,
                                       key_info=_KEY_ID),
            flags={KeyringTraceFlag.GENERATED_DATA_KEY},
        )
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
"""Unit tests for base keyring."""

import pytest

from aws_encryption_sdk.identifiers import Algorithm
from aws_encryption_sdk.keyrings.base import Keyring
from aws_encryption_sdk.materials_managers import DecryptionMaterials, EncryptionMaterials

pytestmark = [pytest.mark.unit, pytest.mark.local]

_encryption_materials = EncryptionMaterials(
    algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384,
    encryption_context={
        "encryption": "context",
        "values": "here"
    },
    signing_key=b"aws-crypto-public-key",
)

_decryption_materials = DecryptionMaterials(
    algorithm=Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384,
    verification_key=b"ex_verification_key")

_encrypted_data_keys = []


def test_keyring_no_encrypt():
    with pytest.raises(NotImplementedError) as exc_info:
        Keyring().on_encrypt(encryption_materials=_encryption_materials)
    assert exc_info.match("Keyring does not implement on_encrypt function")
Exemple #20
0
def encryption_materials_for_discovery_decrypt(fake_generator):
    encrypting_keyring = _AwsKmsSingleCmkKeyring(key_id=fake_generator, client_supplier=DefaultClientSupplier())

    initial_encryption_materials = EncryptionMaterials(algorithm=ALGORITHM, encryption_context={})

    return fake_generator, encrypting_keyring.on_encrypt(initial_encryption_materials)