Beispiel #1
0
    def _prep_message(self):
        """Performs initial message setup.

        :raises MasterKeyProviderError: if primary master key is not a member of supplied MasterKeyProvider
        :raises MasterKeyProviderError: if no Master Keys are returned from key_provider
        """
        validate_commitment_policy_on_encrypt(self.config.commitment_policy,
                                              self.config.algorithm)

        try:
            plaintext_length = self.stream_length
        except NotSupportedError:
            plaintext_length = None
        encryption_materials_request = EncryptionMaterialsRequest(
            algorithm=self.config.algorithm,
            encryption_context=self.config.encryption_context.copy(),
            frame_length=self.config.frame_length,
            plaintext_rostream=aws_encryption_sdk.internal.utils.streams.
            ROStream(self.source_stream),
            plaintext_length=plaintext_length,
            commitment_policy=self.config.commitment_policy,
        )
        self._encryption_materials = self.config.materials_manager.get_encryption_materials(
            request=encryption_materials_request)

        if self.config.algorithm is not None and self._encryption_materials.algorithm != self.config.algorithm:
            raise ActionNotAllowedError(
                ("Cryptographic materials manager provided algorithm suite"
                 " differs from algorithm suite in request.\n"
                 "Required: {requested}\n"
                 "Provided: {provided}").format(
                     requested=self.config.algorithm,
                     provided=self._encryption_materials.algorithm))

        if self._encryption_materials.signing_key is None:
            self.signer = None
        else:
            self.signer = Signer.from_key_bytes(
                algorithm=self._encryption_materials.algorithm,
                key_bytes=self._encryption_materials.signing_key)
        aws_encryption_sdk.internal.utils.validate_frame_length(
            frame_length=self.config.frame_length,
            algorithm=self._encryption_materials.algorithm)

        message_id = aws_encryption_sdk.internal.utils.message_id(
            self._encryption_materials.algorithm.message_id_length())

        self._derived_data_key = derive_data_encryption_key(
            source_key=self._encryption_materials.data_encryption_key.data_key,
            algorithm=self._encryption_materials.algorithm,
            message_id=message_id,
        )

        self._header = self.generate_header(message_id)

        self._write_header()
        if self.content_type == ContentType.NO_FRAMING:
            self._prep_non_framed()
        self._message_prepped = True
Beispiel #2
0
def test_encryption_cycle_with_caching():
    algorithm = Algorithm.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384
    frame_length = 1024
    key_provider = fake_kms_key_provider(algorithm.kdf_input_len)
    cache = aws_encryption_sdk.LocalCryptoMaterialsCache(capacity=10)
    ccmm = aws_encryption_sdk.CachingCryptoMaterialsManager(
        master_key_provider=key_provider, cache=cache, max_age=3600.0, max_messages_encrypted=5
    )
    encrypt_kwargs = dict(
        source=VALUES["plaintext_128"],
        materials_manager=ccmm,
        encryption_context=VALUES["encryption_context"],
        frame_length=frame_length,
        algorithm=algorithm,
    )
    encrypt_cache_key = build_encryption_materials_cache_key(
        partition=ccmm.partition_name,
        request=EncryptionMaterialsRequest(
            encryption_context=VALUES["encryption_context"],
            frame_length=frame_length,
            algorithm=algorithm,
            plaintext_length=len(VALUES["plaintext_128"]),
        ),
    )
    ciphertext, header = aws_encryption_sdk.encrypt(**encrypt_kwargs)
    decrypt_cache_key = build_decryption_materials_cache_key(
        partition=ccmm.partition_name,
        request=DecryptionMaterialsRequest(
            algorithm=algorithm,
            encrypted_data_keys=header.encrypted_data_keys,
            encryption_context=header.encryption_context,
        ),
    )

    assert len(cache._cache) == 1
    assert cache._cache[encrypt_cache_key].messages_encrypted == 1
    assert cache._cache[encrypt_cache_key].bytes_encrypted == 128

    _, _ = aws_encryption_sdk.decrypt(source=ciphertext, materials_manager=ccmm)

    assert len(cache._cache) == 2
    assert decrypt_cache_key in cache._cache

    _, _ = aws_encryption_sdk.encrypt(**encrypt_kwargs)
    _, _ = aws_encryption_sdk.encrypt(**encrypt_kwargs)
    _, _ = aws_encryption_sdk.encrypt(**encrypt_kwargs)

    assert len(cache._cache) == 2
    assert cache._cache[encrypt_cache_key].messages_encrypted == 4
    assert cache._cache[encrypt_cache_key].bytes_encrypted == 512

    _, _ = aws_encryption_sdk.encrypt(**encrypt_kwargs)
    _, _ = aws_encryption_sdk.encrypt(**encrypt_kwargs)
    _, _ = aws_encryption_sdk.encrypt(**encrypt_kwargs)

    assert len(cache._cache) == 2
    assert cache._cache[encrypt_cache_key].messages_encrypted == 2
    assert cache._cache[encrypt_cache_key].bytes_encrypted == 256
def test_encryption_materials_request_attributes_defaults():
    test = EncryptionMaterialsRequest(
        encryption_context={},
        frame_length=5,
        commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT,
    )
    assert test.plaintext_rostream is None
    assert test.algorithm is None
    assert test.plaintext_length is None
def test_encrypt_with_keyring_materials_incomplete(algorithm_suite):
    raw_aes256_keyring = ephemeral_raw_aes_keyring(
        WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING)

    encrypt_cmm = DefaultCryptoMaterialsManager(
        keyring=NoEncryptedDataKeysKeyring(inner_keyring=raw_aes256_keyring))

    encryption_materials_request = EncryptionMaterialsRequest(
        encryption_context={}, frame_length=1024, algorithm=algorithm_suite)

    with pytest.raises(InvalidCryptographicMaterialsError) as excinfo:
        encrypt_cmm.get_encryption_materials(encryption_materials_request)

    excinfo.match("Encryption materials are incomplete!")
def test_encrypt_with_keyring_materials_do_not_match_request(
        kwargs, algorithm_suite):
    raw_aes256_keyring = ephemeral_raw_aes_keyring(
        WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING)

    encrypt_cmm = DefaultCryptoMaterialsManager(
        keyring=BrokenKeyring(inner_keyring=raw_aes256_keyring, **kwargs))

    encryption_materials_request = EncryptionMaterialsRequest(
        encryption_context={}, frame_length=1024, algorithm=algorithm_suite)

    with pytest.raises(InvalidCryptographicMaterialsError) as excinfo:
        encrypt_cmm.get_encryption_materials(encryption_materials_request)

    excinfo.match("Encryption materials do not match request!")
def test_decrypt_with_keyring_materials_incomplete(algorithm_suite):
    raw_aes256_keyring = ephemeral_raw_aes_keyring(
        WrappingAlgorithm.AES_256_GCM_IV12_TAG16_NO_PADDING)
    raw_aes128_keyring = ephemeral_raw_aes_keyring(
        WrappingAlgorithm.AES_128_GCM_IV12_TAG16_NO_PADDING)

    encrypt_cmm = DefaultCryptoMaterialsManager(keyring=raw_aes256_keyring)
    decrypt_cmm = DefaultCryptoMaterialsManager(keyring=raw_aes128_keyring)

    encryption_materials_request = EncryptionMaterialsRequest(
        encryption_context={}, frame_length=1024, algorithm=algorithm_suite)
    encryption_materials = encrypt_cmm.get_encryption_materials(
        encryption_materials_request)

    decryption_materials_request = DecryptionMaterialsRequest(
        algorithm=encryption_materials.algorithm,
        encrypted_data_keys=encryption_materials.encrypted_data_keys,
        encryption_context=encryption_materials.encryption_context,
    )

    with pytest.raises(InvalidCryptographicMaterialsError) as excinfo:
        decrypt_cmm.decrypt_materials(decryption_materials_request)

    excinfo.match("Decryption materials are incomplete!")
Beispiel #7
0
def test_encryption_materials_request_attributes_defaults():
    test = EncryptionMaterialsRequest(encryption_context={}, frame_length=5)
    assert test.plaintext_rostream is None
    assert test.algorithm is None
    assert test.plaintext_length is None
Beispiel #8
0
@pytest.mark.parametrize(
    'encryption_context, result',
    [(entry['raw'], entry['hash'])
     for entry in VALUES['basic']['encryption_context'].values()])
def test_encryption_context_hash(encryption_context, result):
    hasher = hashes.Hash(hashes.SHA512(), backend=default_backend())
    assert _encryption_context_hash(hasher,
                                    encryption_context) == b64decode(result)


@pytest.mark.parametrize(
    'inner_request, result',
    [(dict(partition=scenario['components']['partition_name'],
           request=EncryptionMaterialsRequest(
               encryption_context=scenario['components']['encryption_context'],
               frame_length=0,
               algorithm=scenario['components']['algorithm'])), scenario['id'])
     for scenario in VALUES['cache_ids']['encrypt']])
def test_build_encryption_materials_cache_key(inner_request, result):
    assert build_encryption_materials_cache_key(
        **inner_request) == b64decode(result)


@pytest.mark.parametrize(
    'encrypted_data_keys, result',
    ((set([VALUES['basic']['encrypted_data_keys'][0]['key']
           ]), [VALUES['basic']['encrypted_data_keys'][0]['hash']]),
     (set([VALUES['basic']['encrypted_data_keys'][1]['key']
           ]), [VALUES['basic']['encrypted_data_keys'][1]['hash']]), ([
               VALUES['basic']['encrypted_data_keys'][1]['key'],
               VALUES['basic']['encrypted_data_keys'][0]['key']
Beispiel #9
0
)
def test_encryption_context_hash(encryption_context, result):
    hasher = hashes.Hash(hashes.SHA512(), backend=default_backend())
    assert _encryption_context_hash(hasher,
                                    encryption_context) == b64decode(result)


@pytest.mark.parametrize(
    "inner_request, result",
    [(
        dict(
            partition=scenario["components"]["partition_name"],
            request=EncryptionMaterialsRequest(
                encryption_context=scenario["components"]
                ["encryption_context"],
                frame_length=0,
                algorithm=scenario["components"]["algorithm"],
                commitment_policy=scenario["components"]["commitment_policy"],
            ),
        ),
        scenario["id"],
    ) for scenario in VALUES["cache_ids"]["encrypt"]],
)
def test_build_encryption_materials_cache_key(inner_request, result):
    assert build_encryption_materials_cache_key(
        **inner_request) == b64decode(result)


@pytest.mark.parametrize(
    "encrypted_data_keys, result",
    (
    def _prep_message(self):
        """Performs initial message setup.

        :raises MasterKeyProviderError: if primary master key is not a member of supplied MasterKeyProvider
        :raises MasterKeyProviderError: if no Master Keys are returned from key_provider
        """
        message_id = aws_encryption_sdk.internal.utils.message_id()

        try:
            plaintext_length = self.stream_length
        except NotSupportedError:
            plaintext_length = None
        encryption_materials_request = EncryptionMaterialsRequest(
            algorithm=self.config.algorithm,
            encryption_context=self.config.encryption_context.copy(),
            frame_length=self.config.frame_length,
            plaintext_rostream=aws_encryption_sdk.internal.utils.ROStream(
                self.source_stream),
            plaintext_length=plaintext_length)
        self._encryption_materials = self.config.materials_manager.get_encryption_materials(
            request=encryption_materials_request)

        if self.config.algorithm is not None and self._encryption_materials.algorithm != self.config.algorithm:
            raise ActionNotAllowedError(
                ('Cryptographic materials manager provided algorithm suite'
                 ' differs from algorithm suite in request.\n'
                 'Required: {requested}\n'
                 'Provided: {provided}').format(
                     requested=self.config.algorithm,
                     provided=self._encryption_materials.algorithm))

        if self._encryption_materials.signing_key is None:
            self.signer = None
        else:
            self.signer = aws_encryption_sdk.internal.crypto.Signer.from_key_bytes(
                algorithm=self._encryption_materials.algorithm,
                key_bytes=self._encryption_materials.signing_key)
        aws_encryption_sdk.internal.utils.validate_frame_length(
            frame_length=self.config.frame_length,
            algorithm=self._encryption_materials.algorithm)

        self._derived_data_key = aws_encryption_sdk.internal.crypto.derive_data_encryption_key(
            source_key=self._encryption_materials.data_encryption_key.data_key,
            algorithm=self._encryption_materials.algorithm,
            message_id=message_id)

        self._header = MessageHeader(
            version=VERSION,
            type=TYPE,
            algorithm=self._encryption_materials.algorithm,
            message_id=message_id,
            encryption_context=self._encryption_materials.encryption_context,
            encrypted_data_keys=self._encryption_materials.encrypted_data_keys,
            content_type=self.content_type,
            content_aad_length=0,
            header_iv_length=self._encryption_materials.algorithm.iv_len,
            frame_length=self.config.frame_length)
        self._write_header()
        if self.content_type == ContentType.NO_FRAMING:
            self._prep_non_framed()
        self._message_prepped = True