3.2. Serialization API

You will likely find yourself wishing to encrypt, save, or load various Python structures (specifically, arbitrary nestings of Python lists and dictionaries) in the Dataserver while developing your client implementation for this project.

We provide a util module that provides the following functions that allow you to “serialize” your objects to JSON-encoded byte strings so that they can be stored in the Dataserver.

3.2.1. Functions

util.ObjectToBytes(o: list | Dict) bytes

Converts o into a byte string containing the JSON representation of the struct.

o can be any arbitrary nesting of Python lists or dictionaries containing ints, floats, bools, strs, Nones, and bytes.

Parameters:

o (Union[list, Dict]) – The Python list or dictionary to serialize

Returns:

The serialized form of o

Return type:

bytes

Raises:

ValueError – if o was not a serializable type (i.e. not a Python list or dictionary)

Example usage:

 1# Serialize a Python list to its byte representation:
 2example1 = ["simple", "list"]
 3example1_bytes = util.ObjectToBytes(example1)
 4
 5# Serialize a simple Python dictionary:
 6example2 = {"k1": "v1", "k2": 2, "k3": "v3"}
 7example2_bytes = util.ObjectToBytes(example2)
 8
 9# Serialize a very complex Python dictionary / list structure:
10example3 = {
11    "k1": [{"k2": 2, "k3": [1,2,3], "k4": {"k5": [4,5,6]}}, "string"],
12    "k6": ["this", "is", "a", "list", "of", "strings"],
13    "k7": [b'bytes', b'will', b'also', b'work!'],
14    b'k8': {b'look': "keys can be bytes too!"}
15}
16example3_bytes = util.ObjectToBytes(example3)
util.BytesToObject(b: bytes) list | Dict

Converts a byte string generated by util.ObjectToBytes back into a Python list or dictionary.

Returns:

The deserialized form of b, as either a Python list or dictionary

Return type:

Union[list, Dict]

Raises:

ValueError – if b could not be serialized into a valid Python type (i.e. was not in a valid format due to data corruption)

Example usage:

 1# Serialize a Python list to its byte representation:
 2original_list = ["list", "of", "strings", "and", "nums", 1, 2, 3]
 3byte_list = util.ObjectToBytes(original_list)
 4
 5# Store this byte representation in the Dataserver:
 6loc = memloc.Make()
 7dataserver.Set(loc, byte_list)
 8
 9# Later on, recover the list from the Dataserver:
10result = dataserver.Get(loc)
11try:
12    recovered_list = util.BytesToObject(result)
13    assert(original_list == recovered_list)
14except ValueError:
15    # Something bad happened!

3.2.2. Asymmetric Key Serialization Example

To serialize public and private keys:

# Generate and save some public keys:
verify_key, sign_key = crypto.SignatureKeyGen()

# Upload the public key to the keyserver:
keyserver.Set("bob-verify", verify_key)
assert(verify_key == keyserver.Get("bob-verify"))

# Store the private key on dataserver in plaintext by first converting it to
# a `bytes` instance (don't actually store private keys on the dataserver in
# plaintext!):
sign_addr = memloc.Make()
dataserver.Set(sign_addr, bytes(sign_key))

# Load the key back from bytes; make sure to use the right class! Since
# we expect this to be an instance of a `SignatureSignKey`, use that
# class's `from_bytes` static method:
sign_bytes = dataserver.Get(sign_addr)
recovered_key = crypto.SignatureSignKey.from_bytes(sign_bytes)

# Check that the two keys are equal to each other:
assert(sign_key == recovered_key)