Exemplo n.º 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
Exemplo n.º 2
0
    def _read_header(self):
        """Reads the message header from the input stream.

        :returns: tuple containing deserialized header and header_auth objects
        :rtype: tuple of aws_encryption_sdk.structures.MessageHeader
            and aws_encryption_sdk.internal.structures.MessageHeaderAuthentication
        :raises CustomMaximumValueExceeded: if frame length is greater than the custom max value
        """
        header, raw_header = aws_encryption_sdk.internal.formatting.deserialize.deserialize_header(self.source_stream)

        if (
                self.config.max_body_length is not None
                and header.content_type == ContentType.FRAMED_DATA
                and header.frame_length > self.config.max_body_length
        ):
            raise CustomMaximumValueExceeded(
                'Frame Size in header found larger than custom value: {found} > {custom}'.format(
                    found=header.frame_length,
                    custom=self.config.max_body_length
                )
            )

        decrypt_materials_request = DecryptionMaterialsRequest(
            encrypted_data_keys=header.encrypted_data_keys,
            algorithm=header.algorithm,
            encryption_context=header.encryption_context
        )
        decryption_materials = self.config.materials_manager.decrypt_materials(request=decrypt_materials_request)
        if decryption_materials.verification_key is None:
            self.verifier = None
        else:
            self.verifier = Verifier.from_key_bytes(
                algorithm=header.algorithm,
                key_bytes=decryption_materials.verification_key
            )
        if self.verifier is not None:
            self.verifier.update(raw_header)

        header_auth = aws_encryption_sdk.internal.formatting.deserialize.deserialize_header_auth(
            stream=self.source_stream,
            algorithm=header.algorithm,
            verifier=self.verifier
        )
        self._derived_data_key = derive_data_encryption_key(
            source_key=decryption_materials.data_key.data_key,
            algorithm=header.algorithm,
            message_id=header.message_id
        )
        aws_encryption_sdk.internal.formatting.deserialize.validate_header(
            header=header,
            header_auth=header_auth,
            raw_header=raw_header,
            data_key=self._derived_data_key
        )
        return header, header_auth
Exemplo n.º 3
0
def test_derive_data_encryption_key_with_hkdf(patch_default_backend, patch_struct):
    algorithm = MagicMock()
    algorithm.kdf_hash_type.return_value = sentinel.kdf_hash_type
    test = derive_data_encryption_key(
        source_key=sentinel.source_key, algorithm=algorithm, message_id=sentinel.message_id
    )
    patch_struct.pack.assert_called_with(">H16s", algorithm.algorithm_id, sentinel.message_id)
    algorithm.kdf_type.assert_called_with(
        algorithm=sentinel.kdf_hash_type,
        length=algorithm.data_key_len,
        salt=None,
        info=patch_struct.pack.return_value,
        backend=patch_default_backend.return_value,
    )
    algorithm.kdf_type.return_value.derive.assert_called_with(sentinel.source_key)
    assert test == algorithm.kdf_type.return_value.derive.return_value
Exemplo n.º 4
0
def test_derive_data_encryption_key_with_hkdf_committing(patch_default_backend, patch_struct):
    algorithm = MagicMock()
    algorithm.kdf_hash_type.return_value = sentinel.kdf_hash_type
    algorithm.data_key_len = sentinel.data_key_len
    algorithm.is_committing.return_value = True
    test = data_keys.derive_data_encryption_key(
        source_key=sentinel.source_key, algorithm=algorithm, message_id=sentinel.message_id
    )
    patch_struct.pack.assert_called_with(">H9s", algorithm.algorithm_id, data_keys.KEY_LABEL)
    algorithm.kdf_type.assert_called_with(
        algorithm=sentinel.kdf_hash_type,
        length=sentinel.data_key_len,
        salt=sentinel.message_id,
        info=patch_struct.pack.return_value,
        backend=patch_default_backend.return_value,
    )
    algorithm.kdf_type.return_value.derive.assert_called_with(sentinel.source_key)
    assert test == algorithm.kdf_type.return_value.derive.return_value
def test_derive_data_encryption_key_no_hkdf():
    algorithm = MagicMock(kdf_type=None)
    test = data_keys.derive_data_encryption_key(source_key=sentinel.source_key,
                                                algorithm=algorithm,
                                                message_id=sentinel.message_id)
    assert test == sentinel.source_key
Exemplo n.º 6
0
    def _read_header(self):
        """Reads the message header from the input stream.

        :returns: tuple containing deserialized header and header_auth objects
        :rtype: tuple of aws_encryption_sdk.structures.MessageHeader
            and aws_encryption_sdk.internal.structures.MessageHeaderAuthentication
        :raises CustomMaximumValueExceeded: if frame length is greater than the custom max value
        """
        header, raw_header = deserialize_header(self.source_stream)
        self.__unframed_bytes_read += len(raw_header)

        validate_commitment_policy_on_decrypt(self.config.commitment_policy,
                                              header.algorithm)

        if (self.config.max_body_length is not None
                and header.content_type == ContentType.FRAMED_DATA
                and header.frame_length > self.config.max_body_length):
            raise CustomMaximumValueExceeded(
                "Frame Size in header found larger than custom value: {found:d} > {custom:d}"
                .format(found=header.frame_length,
                        custom=self.config.max_body_length))

        decrypt_materials_request = DecryptionMaterialsRequest(
            encrypted_data_keys=header.encrypted_data_keys,
            algorithm=header.algorithm,
            encryption_context=header.encryption_context,
            commitment_policy=self.config.commitment_policy,
        )
        decryption_materials = self.config.materials_manager.decrypt_materials(
            request=decrypt_materials_request)
        if decryption_materials.verification_key is None:
            self.verifier = None
        else:
            self.verifier = Verifier.from_key_bytes(
                algorithm=header.algorithm,
                key_bytes=decryption_materials.verification_key)
        if self.verifier is not None:
            self.verifier.update(raw_header)

        header_auth = deserialize_header_auth(version=header.version,
                                              stream=self.source_stream,
                                              algorithm=header.algorithm,
                                              verifier=self.verifier)
        self._derived_data_key = derive_data_encryption_key(
            source_key=decryption_materials.data_key.data_key,
            algorithm=header.algorithm,
            message_id=header.message_id)

        if header.algorithm.is_committing():
            expected_commitment_key = calculate_commitment_key(
                source_key=decryption_materials.data_key.data_key,
                algorithm=header.algorithm,
                message_id=header.message_id,
            )

            if not hmac.compare_digest(expected_commitment_key,
                                       header.commitment_key):
                raise MasterKeyProviderError(
                    "Key commitment validation failed. Key identity does not match the identity asserted in the "
                    "message. Halting processing of this message.")

        validate_header(header=header,
                        header_auth=header_auth,
                        raw_header=raw_header,
                        data_key=self._derived_data_key)

        return header, header_auth