2021-03-04 15:25:36 +00:00
|
|
|
# Copyright New York University and the TUF contributors
|
|
|
|
|
# SPDX-License-Identifier: MIT OR Apache-2.0
|
|
|
|
|
|
2021-09-23 14:19:05 +00:00
|
|
|
"""``tuf.api.serialization.json`` module provides concrete implementations to
|
|
|
|
|
serialize and deserialize TUF role metadata to and from the JSON wireline
|
|
|
|
|
format for transportation, and to serialize the 'signed' part of TUF role
|
|
|
|
|
metadata to the OLPC Canonical JSON format for signature generation and
|
|
|
|
|
verification.
|
2021-02-08 16:32:06 +00:00
|
|
|
"""
|
2021-09-23 14:19:05 +00:00
|
|
|
|
2021-02-08 16:32:06 +00:00
|
|
|
import json
|
|
|
|
|
|
|
|
|
|
from securesystemslib.formats import encode_canonical
|
|
|
|
|
|
2021-03-04 09:51:45 +00:00
|
|
|
# pylint: disable=cyclic-import
|
2021-03-04 15:31:36 +00:00
|
|
|
# ... to allow de/serializing Metadata and Signed objects here, while also
|
|
|
|
|
# creating default de/serializers there (see metadata local scope imports).
|
|
|
|
|
# NOTE: A less desirable alternative would be to add more abstraction layers.
|
2021-02-08 16:32:06 +00:00
|
|
|
from tuf.api.metadata import Metadata, Signed
|
2021-03-11 17:00:19 +00:00
|
|
|
from tuf.api.serialization import (
|
|
|
|
|
DeserializationError,
|
|
|
|
|
MetadataDeserializer,
|
|
|
|
|
MetadataSerializer,
|
|
|
|
|
SerializationError,
|
|
|
|
|
SignedSerializer,
|
|
|
|
|
)
|
2021-02-08 16:32:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class JSONDeserializer(MetadataDeserializer):
|
2021-04-27 11:08:24 +00:00
|
|
|
"""Provides JSON to Metadata deserialize method."""
|
2021-02-08 16:32:06 +00:00
|
|
|
|
|
|
|
|
def deserialize(self, raw_data: bytes) -> Metadata:
|
2021-04-27 11:08:24 +00:00
|
|
|
"""Deserialize utf-8 encoded JSON bytes into Metadata object."""
|
2021-02-09 14:36:49 +00:00
|
|
|
try:
|
2021-03-05 10:46:00 +00:00
|
|
|
json_dict = json.loads(raw_data.decode("utf-8"))
|
2021-03-05 11:54:31 +00:00
|
|
|
metadata_obj = Metadata.from_dict(json_dict)
|
2021-02-09 14:36:49 +00:00
|
|
|
|
2021-09-01 14:37:03 +00:00
|
|
|
except Exception as e:
|
2021-03-09 16:27:39 +00:00
|
|
|
raise DeserializationError from e
|
2021-02-08 16:32:06 +00:00
|
|
|
|
2021-03-05 11:54:31 +00:00
|
|
|
return metadata_obj
|
|
|
|
|
|
2021-02-08 16:32:06 +00:00
|
|
|
|
|
|
|
|
class JSONSerializer(MetadataSerializer):
|
2021-03-09 16:35:08 +00:00
|
|
|
"""Provides Metadata to JSON serialize method.
|
2021-02-08 16:32:06 +00:00
|
|
|
|
|
|
|
|
Attributes:
|
|
|
|
|
compact: A boolean indicating if the JSON bytes generated in
|
|
|
|
|
'serialize' should be compact by excluding whitespace.
|
|
|
|
|
|
|
|
|
|
"""
|
2021-03-11 17:00:19 +00:00
|
|
|
|
2021-09-23 14:57:19 +00:00
|
|
|
def __init__(self, compact: bool = False):
|
2021-02-08 16:32:06 +00:00
|
|
|
self.compact = compact
|
|
|
|
|
|
|
|
|
|
def serialize(self, metadata_obj: Metadata) -> bytes:
|
2021-04-27 11:08:24 +00:00
|
|
|
"""Serialize Metadata object into utf-8 encoded JSON bytes."""
|
2021-02-09 14:36:49 +00:00
|
|
|
try:
|
2021-03-11 17:00:19 +00:00
|
|
|
indent = None if self.compact else 1
|
|
|
|
|
separators = (",", ":") if self.compact else (",", ": ")
|
|
|
|
|
json_bytes = json.dumps(
|
|
|
|
|
metadata_obj.to_dict(),
|
|
|
|
|
indent=indent,
|
|
|
|
|
separators=separators,
|
|
|
|
|
sort_keys=True,
|
|
|
|
|
).encode("utf-8")
|
|
|
|
|
|
2021-09-01 14:37:03 +00:00
|
|
|
except Exception as e:
|
2021-03-09 16:27:39 +00:00
|
|
|
raise SerializationError from e
|
2021-02-08 16:32:06 +00:00
|
|
|
|
2021-03-05 11:54:31 +00:00
|
|
|
return json_bytes
|
|
|
|
|
|
2021-02-08 16:32:06 +00:00
|
|
|
|
|
|
|
|
class CanonicalJSONSerializer(SignedSerializer):
|
2021-04-27 11:08:24 +00:00
|
|
|
"""Provides Signed to OLPC Canonical JSON serialize method."""
|
2021-02-08 16:32:06 +00:00
|
|
|
|
|
|
|
|
def serialize(self, signed_obj: Signed) -> bytes:
|
2021-03-09 16:35:08 +00:00
|
|
|
"""Serialize Signed object into utf-8 encoded OLPC Canonical JSON
|
|
|
|
|
bytes.
|
|
|
|
|
"""
|
2021-02-09 14:36:49 +00:00
|
|
|
try:
|
2021-03-04 11:46:16 +00:00
|
|
|
signed_dict = signed_obj.to_dict()
|
2021-03-05 11:54:31 +00:00
|
|
|
canonical_bytes = encode_canonical(signed_dict).encode("utf-8")
|
2021-02-09 14:36:49 +00:00
|
|
|
|
2021-09-01 14:37:03 +00:00
|
|
|
except Exception as e:
|
2021-03-09 16:27:39 +00:00
|
|
|
raise SerializationError from e
|
2021-03-05 11:54:31 +00:00
|
|
|
|
|
|
|
|
return canonical_bytes
|