Ejemplo n.º 1
0
    def _deserialize_function(tag):
        # type: (bytes) -> Callable
        """Identifies the correct deserialization function based on the provided tag.

        :param tag: Identifying tag, read from start of serialized object
        :type tag: dynamodb_encryption_sdk.internal.identifiers.Tag
        :rtype: callable
        """
        # for some reason pylint can't follow the Enum member attributes
        deserialize_functions = {
            Tag.BINARY.tag: _deserialize_binary,  # pylint: disable=no-member
            Tag.BINARY_SET.tag: _deserialize_binary_set,  # pylint: disable=no-member
            Tag.NUMBER.tag: _deserialize_number,  # pylint: disable=no-member
            Tag.NUMBER_SET.tag: _deserialize_number_set,  # pylint: disable=no-member
            Tag.STRING.tag: _deserialize_string,  # pylint: disable=no-member
            Tag.STRING_SET.tag: _deserialize_string_set,  # pylint: disable=no-member
            Tag.BOOLEAN.tag: _deserialize_boolean,  # pylint: disable=no-member
            Tag.NULL.tag: _deserialize_null,  # pylint: disable=no-member
            Tag.LIST.tag: _deserialize_list,  # pylint: disable=no-member
            Tag.MAP.tag: _deserialize_map,  # pylint: disable=no-member
        }
        try:
            return deserialize_functions[tag]
        except KeyError:
            raise DeserializationError('Unsupported tag: "{}"'.format(tag))
    def _deserialize(stream):
        # type: (io.BytesIO) -> Dict[Text, dynamodb_types.RAW_ATTRIBUTE]
        """Deserializes a serialized object.

        :param stream: Stream containing serialized object
        :type stream: io.BytesIO
        :rtype: dict
        """
        try:
            tag = decode_tag(stream)
            return _deserialize_function(tag)(stream)
        except struct.error:
            raise DeserializationError("Malformed serialized data")
Ejemplo n.º 3
0
def decode_tag(stream):
    """Decode a tag value from a serialized stream.

    :param stream: Source data stream
    :type stream: io.BytesIO
    :returns: Decoded tag
    :rtype: bytes
    """
    (reserved, tag) = unpack_value(">cc", stream)

    if reserved != b"\x00":
        raise DeserializationError("Invalid tag: reserved byte is not null")

    return tag
    def _deserialize_map(stream):
        # type: (io.BytesIO) -> Dict[Text, dynamodb_types.MAP]
        """Deserializes a map object.

        :param stream: Stream containing serialized object
        :type stream: io.BytesIO
        :rtype: dict
        """
        member_count = decode_length(stream)
        members = {}  # type: dynamodb_types.MAP
        for _ in range(member_count):
            key = _deserialize(stream)
            if Tag.STRING.dynamodb_tag not in key:
                raise DeserializationError(
                    'Malformed serialized map: found "{}" as map key.'.format(list(key.keys())[0])
                )

            value = _deserialize(stream)
            members[key[Tag.STRING.dynamodb_tag]] = value

        return {Tag.MAP.dynamodb_tag: members}
def deserialize_attribute(serialized_attribute):  # noqa: C901 pylint: disable=too-many-locals
    # type: (bytes) -> dynamodb_types.RAW_ATTRIBUTE
    """Deserializes serialized attributes for decryption.

    :param bytes serialized_attribute: Serialized attribute bytes
    :returns: Deserialized attribute
    :rtype: dict
    """

    def _transform_binary_value(value):
        # (bytes) -> bytes
        """Transforms a serialized binary value.

        :param bytes value: Raw deserialized value
        :rtype: bytes
        """
        if isinstance(value, Binary):
            return value.value
        return value

    def _deserialize_binary(stream):
        # type: (io.BytesIO) -> Dict[Text, bytes]
        """Deserializes a binary object.

        :param stream: Stream containing serialized object
        :type stream: io.BytesIO
        :rtype: dict
        """
        value = decode_value(stream)
        return {Tag.BINARY.dynamodb_tag: _transform_binary_value(value)}

    def _transform_string_value(value):
        # (bytes) -> dynamodb_types.STRING
        """Transforms a serialized string value.

        :param bytes value: Raw deserialized value
        :rtype: dynamodb_encryption_sdk.internal.dynamodb_types.STRING
        """
        return codecs.decode(value, TEXT_ENCODING)

    def _deserialize_string(stream):
        # type: (io.BytesIO) -> Dict[Text, dynamodb_types.STRING]
        """Deserializes a string object.

        :param stream: Stream containing serialized object
        :type stream: io.BytesIO
        :rtype: dict
        """
        value = decode_value(stream)
        return {Tag.STRING.dynamodb_tag: _transform_string_value(value)}

    def _transform_number_value(value):
        # (bytes) -> dynamodb_types.STRING
        """Transforms a serialized number value.

        :param bytes value: Raw deserialized value
        :rtype: dynamodb_encryption_sdk.internal.dynamodb_types.STRING
        """
        raw_value = codecs.decode(value, TEXT_ENCODING)
        decimal_value = Decimal(to_str(raw_value)).normalize()
        return "{0:f}".format(decimal_value)

    def _deserialize_number(stream):
        # type: (io.BytesIO) -> Dict[Text, dynamodb_types.STRING]
        """Deserializes a number object.

        :param stream: Stream containing serialized object
        :type stream: io.BytesIO
        :rtype: dict
        """
        value = decode_value(stream)
        return {Tag.NUMBER.dynamodb_tag: _transform_number_value(value)}

    _boolean_map = {TagValues.FALSE.value: False, TagValues.TRUE.value: True}

    def _deserialize_boolean(stream):
        # type: (io.BytesIO) -> Dict[Text, dynamodb_types.BOOLEAN]
        """Deserializes a boolean object.

        :param stream: Stream containing serialized object
        :type stream: io.BytesIO
        :rtype: dict
        """
        value = decode_byte(stream)
        return {Tag.BOOLEAN.dynamodb_tag: _boolean_map[value]}

    def _deserialize_null(stream):  # we want a consistent API but don't use stream, so pylint: disable=unused-argument
        # type: (io.BytesIO) -> Dict[Text, dynamodb_types.BOOLEAN]
        """Deserializes a null object.

        :param stream: Stream containing serialized object
        :type stream: io.BytesIO
        :rtype: dict
        """
        return {Tag.NULL.dynamodb_tag: True}

    def _deserialize_set(stream, member_transform):
        # type: (io.BytesIO, Callable) -> List[Union[dynamodb_types.BINARY, dynamodb_types.STRING]]
        """Deserializes contents of serialized set.

        :param stream: Stream containing serialized object
        :type stream: io.BytesIO
        :rtype: list
        """
        member_count = decode_length(stream)
        return sorted([member_transform(decode_value(stream)) for _ in range(member_count)])

    def _deserialize_binary_set(stream):
        # type: (io.BytesIO) -> Dict[Text, dynamodb_types.SET[dynamodb_types.BINARY]]
        """Deserializes a binary set object.

        :param stream: Stream containing serialized object
        :type stream: io.BytesIO
        :rtype: dict
        """
        return {Tag.BINARY_SET.dynamodb_tag: _deserialize_set(stream, _transform_binary_value)}

    def _deserialize_string_set(stream):
        # type: (io.BytesIO) -> Dict[Text, dynamodb_types.SET[dynamodb_types.STRING]]
        """Deserializes a string set object.

        :param stream: Stream containing serialized object
        :type stream: io.BytesIO
        :rtype: dict
        """
        return {Tag.STRING_SET.dynamodb_tag: _deserialize_set(stream, _transform_string_value)}

    def _deserialize_number_set(stream):
        # type: (io.BytesIO) -> Dict[Text, dynamodb_types.SET[dynamodb_types.STRING]]
        """Deserializes a number set object.

        :param stream: Stream containing serialized object
        :type stream: io.BytesIO
        :rtype: dict
        """
        return {Tag.NUMBER_SET.dynamodb_tag: _deserialize_set(stream, _transform_number_value)}

    def _deserialize_list(stream):
        # type: (io.BytesIO) -> Dict[Text, dynamodb_types.LIST]
        """Deserializes a list object.

        :param stream: Stream containing serialized object
        :type stream: io.BytesIO
        :rtype: dict
        """
        member_count = decode_length(stream)
        return {Tag.LIST.dynamodb_tag: [_deserialize(stream) for _ in range(member_count)]}

    def _deserialize_map(stream):
        # type: (io.BytesIO) -> Dict[Text, dynamodb_types.MAP]
        """Deserializes a map object.

        :param stream: Stream containing serialized object
        :type stream: io.BytesIO
        :rtype: dict
        """
        member_count = decode_length(stream)
        members = {}  # type: dynamodb_types.MAP
        for _ in range(member_count):
            key = _deserialize(stream)
            if Tag.STRING.dynamodb_tag not in key:
                raise DeserializationError(
                    'Malformed serialized map: found "{}" as map key.'.format(list(key.keys())[0])
                )

            value = _deserialize(stream)
            members[key[Tag.STRING.dynamodb_tag]] = value

        return {Tag.MAP.dynamodb_tag: members}

    def _deserialize_function(tag):
        # type: (bytes) -> Callable
        """Identifies the correct deserialization function based on the provided tag.

        :param tag: Identifying tag, read from start of serialized object
        :type tag: dynamodb_encryption_sdk.internal.identifiers.Tag
        :rtype: callable
        """
        deserialize_functions = {
            Tag.BINARY.tag: _deserialize_binary,
            Tag.BINARY_SET.tag: _deserialize_binary_set,
            Tag.NUMBER.tag: _deserialize_number,
            Tag.NUMBER_SET.tag: _deserialize_number_set,
            Tag.STRING.tag: _deserialize_string,
            Tag.STRING_SET.tag: _deserialize_string_set,
            Tag.BOOLEAN.tag: _deserialize_boolean,
            Tag.NULL.tag: _deserialize_null,
            Tag.LIST.tag: _deserialize_list,
            Tag.MAP.tag: _deserialize_map,
        }
        try:
            return deserialize_functions[tag]
        except KeyError:
            raise DeserializationError('Unsupported tag: "{}"'.format(tag))

    def _deserialize(stream):
        # type: (io.BytesIO) -> Dict[Text, dynamodb_types.RAW_ATTRIBUTE]
        """Deserializes a serialized object.

        :param stream: Stream containing serialized object
        :type stream: io.BytesIO
        :rtype: dict
        """
        try:
            tag = decode_tag(stream)
            return _deserialize_function(tag)(stream)
        except struct.error:
            raise DeserializationError("Malformed serialized data")

    if not serialized_attribute:
        raise DeserializationError("Empty serialized attribute data")

    stream = io.BytesIO(serialized_attribute)
    return _deserialize(stream)