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,None
s, 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)