def _deserialize_header_v1(header, tee_stream, max_encrypted_data_keys):
    # type: (IO, Union[int, None]) -> MessageHeader
    """Deserializes the header from a source stream in SerializationVersion.V1.

    :param header: A dictionary in which to store deserialized values
    :type header: dict
    :param tee_stream: The stream from which to read bytes
    :type tee_stream: aws_encryption_sdk.internal.utils.streams.TeeStream
    :param max_encrypted_data_keys: Maximum number of encrypted keys to deserialize
    :type max_encrypted_data_keys: None or positive int
    :returns: Deserialized MessageHeader object
    :rtype: :class:`aws_encryption_sdk.structures.MessageHeader`
    :raises NotSupportedError: if unsupported data types are found
    :raises UnknownIdentityError: if unknown data types are found
    :raises SerializationError: if IV length does not match algorithm
    """
    _LOGGER.debug("Deserializing header in version V1")

    (message_type_id, ) = unpack_values(">B", tee_stream)
    header["type"] = _verified_message_type_from_id(message_type_id)

    algorithm_id, message_id, ser_encryption_context_length = unpack_values(
        ">H16sH", tee_stream)

    header["algorithm"] = _verified_algorithm_from_id(algorithm_id)
    header["message_id"] = message_id

    header["encryption_context"] = deserialize_encryption_context(
        tee_stream.read(ser_encryption_context_length))

    header["encrypted_data_keys"] = deserialize_encrypted_data_keys(
        tee_stream, max_encrypted_data_keys)

    (content_type_id, ) = unpack_values(">B", tee_stream)
    header["content_type"] = _verified_content_type_from_id(content_type_id)

    (content_aad_length, ) = unpack_values(">I", tee_stream)
    header["content_aad_length"] = _verified_content_aad_length(
        content_aad_length)

    (iv_length, ) = unpack_values(">B", tee_stream)
    header["header_iv_length"] = _verified_iv_length(iv_length,
                                                     header["algorithm"])

    (frame_length, ) = unpack_values(">I", tee_stream)
    header["frame_length"] = _verified_frame_length(frame_length,
                                                    header["content_type"])

    return MessageHeader(**header)
def deserialize_header(stream):
    # type: (IO) -> MessageHeader
    """Deserializes the header from a source stream

    :param stream: Source data stream
    :type stream: io.BytesIO
    :returns: Deserialized MessageHeader object
    :rtype: :class:`aws_encryption_sdk.structures.MessageHeader` and bytes
    :raises NotSupportedError: if unsupported data types are found
    :raises UnknownIdentityError: if unknown data types are found
    :raises SerializationError: if IV length does not match algorithm
    """
    _LOGGER.debug("Starting header deserialization")
    tee = io.BytesIO()
    tee_stream = TeeStream(stream, tee)
    version_id, message_type_id = unpack_values(">BB", tee_stream)
    header = dict()
    header["version"] = _verified_version_from_id(version_id)
    header["type"] = _verified_message_type_from_id(message_type_id)

    algorithm_id, message_id, ser_encryption_context_length = unpack_values(
        ">H16sH", tee_stream)

    header["algorithm"] = _verified_algorithm_from_id(algorithm_id)
    header["message_id"] = message_id

    header["encryption_context"] = deserialize_encryption_context(
        tee_stream.read(ser_encryption_context_length))

    header["encrypted_data_keys"] = _deserialize_encrypted_data_keys(
        tee_stream)

    (content_type_id, ) = unpack_values(">B", tee_stream)
    header["content_type"] = _verified_content_type_from_id(content_type_id)

    (content_aad_length, ) = unpack_values(">I", tee_stream)
    header["content_aad_length"] = _verified_content_aad_length(
        content_aad_length)

    (iv_length, ) = unpack_values(">B", tee_stream)
    header["header_iv_length"] = _verified_iv_length(iv_length,
                                                     header["algorithm"])

    (frame_length, ) = unpack_values(">I", tee_stream)
    header["frame_length"] = _verified_frame_length(frame_length,
                                                    header["content_type"])

    return MessageHeader(**header), tee.getvalue()
def _deserialize_header_v2(header, tee_stream):
    # type: (IO) -> MessageHeader
    """Deserializes the header from a source stream in SerializationVersion.V2.

    :param header: A dictionary in which to store deserialized values
    :type header: dict
    :param tee_stream: The stream from which to read bytes
    :type tee_stream: aws_encryption_sdk.internal.utils.streams.TeeStream
    :returns: Deserialized MessageHeader object
    :rtype: :class:`aws_encryption_sdk.structures.MessageHeader`
    :raises NotSupportedError: if unsupported data types are found
    :raises UnknownIdentityError: if unknown data types are found
    :raises SerializationError: if IV length does not match algorithm
    """
    _LOGGER.debug("Deserializing header in version V2")

    algorithm_id, message_id, ser_encryption_context_length = unpack_values(
        ">H32sH", tee_stream)

    header["algorithm"] = _verified_algorithm_from_id(algorithm_id)
    header["message_id"] = message_id

    header["encryption_context"] = deserialize_encryption_context(
        tee_stream.read(ser_encryption_context_length))

    header["encrypted_data_keys"] = _deserialize_encrypted_data_keys(
        tee_stream)

    (content_type_id, ) = unpack_values(">B", tee_stream)
    header["content_type"] = _verified_content_type_from_id(content_type_id)

    (frame_length, ) = unpack_values(">I", tee_stream)
    header["frame_length"] = _verified_frame_length(frame_length,
                                                    header["content_type"])

    algorithm_suite_data_length = header[
        "algorithm"].algorithm_suite_data_length()
    (algorithm_suite_data, ) = unpack_values(
        ">{}s".format(algorithm_suite_data_length), tee_stream)
    header["commitment_key"] = algorithm_suite_data

    return MessageHeader(**header)
Пример #4
0
def deserialize_header(stream):
    """Deserializes the header from a source stream

    :param stream: Source data stream
    :type stream: io.BytesIO
    :returns: Deserialized MessageHeader object
    :rtype: :class:`aws_encryption_sdk.structures.MessageHeader` and bytes
    :raises NotSupportedError: if unsupported data types are found
    :raises UnknownIdentityError: if unknown data types are found
    :raises SerializationError: if IV length does not match algorithm
    """
    _LOGGER.debug('Starting header deserialization')
    tee = io.BytesIO()
    tee_stream = TeeStream(stream, tee)
    version_id, message_type_id = unpack_values('>BB', tee_stream)
    try:
        message_type = ObjectType(message_type_id)
    except ValueError as error:
        raise NotSupportedError(
            'Unsupported type {} discovered in data stream'.format(
                message_type_id), error)
    try:
        version = SerializationVersion(version_id)
    except ValueError as error:
        raise NotSupportedError('Unsupported version {}'.format(version_id),
                                error)
    header = {'version': version, 'type': message_type}

    algorithm_id, message_id, ser_encryption_context_length = unpack_values(
        '>H16sH', tee_stream)

    try:
        alg = Algorithm.get_by_id(algorithm_id)
    except KeyError as error:
        raise UnknownIdentityError('Unknown algorithm {}'.format(algorithm_id),
                                   error)
    if not alg.allowed:
        raise NotSupportedError('Unsupported algorithm: {}'.format(alg))
    header['algorithm'] = alg
    header['message_id'] = message_id

    header['encryption_context'] = deserialize_encryption_context(
        tee_stream.read(ser_encryption_context_length))
    (encrypted_data_key_count, ) = unpack_values('>H', tee_stream)

    encrypted_data_keys = set([])
    for _ in range(encrypted_data_key_count):
        (key_provider_length, ) = unpack_values('>H', tee_stream)
        (key_provider_identifier, ) = unpack_values(
            '>{}s'.format(key_provider_length), tee_stream)
        (key_provider_information_length, ) = unpack_values('>H', tee_stream)
        (key_provider_information, ) = unpack_values(
            '>{}s'.format(key_provider_information_length), tee_stream)
        (encrypted_data_key_length, ) = unpack_values('>H', tee_stream)
        encrypted_data_key = tee_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))
    header['encrypted_data_keys'] = encrypted_data_keys

    (content_type_id, ) = unpack_values('>B', tee_stream)
    try:
        content_type = ContentType(content_type_id)
    except ValueError as error:
        raise UnknownIdentityError(
            'Unknown content type {}'.format(content_type_id), error)
    header['content_type'] = content_type

    (content_aad_length, ) = unpack_values('>I', tee_stream)
    if content_aad_length != 0:
        raise SerializationError(
            'Content AAD length field is currently unused, its value must be always 0'
        )
    header['content_aad_length'] = 0

    (iv_length, ) = unpack_values('>B', tee_stream)
    if iv_length != alg.iv_len:
        raise SerializationError(
            'Specified IV length ({length}) does not match algorithm IV length ({alg})'
            .format(length=iv_length, alg=alg))
    header['header_iv_length'] = iv_length

    (frame_length, ) = unpack_values('>I', tee_stream)
    if content_type == ContentType.FRAMED_DATA and frame_length > MAX_FRAME_SIZE:
        raise SerializationError(
            'Specified frame length larger than allowed maximum: {found} > {max}'
            .format(found=frame_length, max=MAX_FRAME_SIZE))
    elif content_type == ContentType.NO_FRAMING and frame_length != 0:
        raise SerializationError(
            'Non-zero frame length found for non-framed message')
    header['frame_length'] = frame_length

    return MessageHeader(**header), tee.getvalue()