formatting, whitespace, and some rephrasing for clarity

pull/977/head
Matthew Hodgson 10 years ago
parent 64f56a15d7
commit 2f1f37cc4c

@ -71,15 +71,15 @@ insignificant whitespace, fractions, exponents and redundant character escapes
Signing JSON Signing JSON
------------ ------------
We can now sign a JSON object by encoding it as a sequence of bytes. Computing We can now sign a JSON object by encoding it as a sequence of bytes, computing
the signature for that sequence and then adding the signature to the original the signature for that sequence and then adding the signature to the original
JSON object. JSON object.
Signing Details Signing Details
+++++++++++++++ +++++++++++++++
JSON is signed by encoding the JSON object without ``signatures`` or ``unsigned`` JSON is signed by encoding the JSON object without ``signatures`` or keys grouped
keys using a canonical encoding. The JSON bytes are then signed using the as ``unsigned``, using the canonical encoding described above. The JSON bytes are then signed using the
signature algorithm and the signature encoded using base64 with the padding signature algorithm and the signature encoded using base64 with the padding
stripped. The resulting base64 signature is added to an object under the stripped. The resulting base64 signature is added to an object under the
*signing key identifier* which is added to the ``signatures`` object under the *signing key identifier* which is added to the ``signatures`` object under the
@ -161,23 +161,29 @@ in the event JSON in a ``hash`` object under a ``sha256`` key.
.. code:: python .. code:: python
def hash_event(event_json_object): def hash_event(event_json_object):
# Keys under "unsigned" can be modified by other servers. # Keys under "unsigned" can be modified by other servers.
# They are useful for conveying information like the age of an # They are useful for conveying information like the age of an
# event that will change in transit. # event that will change in transit.
# Since they can be modifed we need to exclude them from the hash. # Since they can be modifed we need to exclude them from the hash.
unsigned = event_json_object.pop("unsigned", None) unsigned = event_json_object.pop("unsigned", None)
# Signatures will depend on the current value of the "hashes" key. # Signatures will depend on the current value of the "hashes" key.
# We cannot add new hashes without invalidating existing signatures. # We cannot add new hashes without invalidating existing signatures.
signatures = event_json_object.pop("signatures", None) signatures = event_json_object.pop("signatures", None)
# The "hashes" key might contain multiple algorithms if we decide to # The "hashes" key might contain multiple algorithms if we decide to
# migrate away from SHA-2. We don't want to include an existing hash # migrate away from SHA-2. We don't want to include an existing hash
# output in our hash so we exclude the "hashes" dict from the hash. # output in our hash so we exclude the "hashes" dict from the hash.
hashes = event_json_object.pop("hashes", {}) hashes = event_json_object.pop("hashes", {})
# Encode the JSON using a canonical encoding so that we get the same # Encode the JSON using a canonical encoding so that we get the same
# bytes on every server for the same JSON object. # bytes on every server for the same JSON object.
event_json_bytes = encode_canonical_json(event_json_bytes) event_json_bytes = encode_canonical_json(event_json_bytes)
# Add the base64 encoded bytes of the hash to the "hashes" dict. # Add the base64 encoded bytes of the hash to the "hashes" dict.
hashes["sha256"] = encode_base64(sha256(event_json_bytes).digest()) hashes["sha256"] = encode_base64(sha256(event_json_bytes).digest())
# Add the "hashes" dict back the event JSON under a "hashes" key. # Add the "hashes" dict back the event JSON under a "hashes" key.
event_json_object["hashes"] = hashes event_json_object["hashes"] = hashes
if unsigned is not None: if unsigned is not None:
@ -191,26 +197,31 @@ signing algorithm
.. code:: python .. code:: python
def sign_event(event_json_object, name, key): def sign_event(event_json_object, name, key):
# Make sure the event has a "hashes" key. # Make sure the event has a "hashes" key.
if "hashes" not in event_json_object: if "hashes" not in event_json_object:
event_json_object = hash_event(event_json_object) event_json_object = hash_event(event_json_object)
# Strip all the keys that would be removed if the event was redacted. # Strip all the keys that would be removed if the event was redacted.
# The hashes are not striped and cover all the keys in the event. # The hashes are not stripped and cover all the keys in the event.
# This means that we can tell if any of the non-essential keys are # This means that we can tell if any of the non-essential keys are
# modified or removed. # modified or removed.
striped_json_object = strip_non_essential_keys(event_json_object) stripped_json_object = strip_non_essential_keys(event_json_object)
# Sign the stripped JSON object. The signature only covers the # Sign the stripped JSON object. The signature only covers the
# essential keys and the hashes. This means that we can check the # essential keys and the hashes. This means that we can check the
# signature even if the event is redacted. # signature even if the event is redacted.
signed_json_object = sign_json(striped_json_object) signed_json_object = sign_json(stripped_json_object)
# Copy the signatures from the striped event to the original event.
# Copy the signatures from the stripped event to the original event.
event_json_object["signatures"] = signed_json_oject["signatures"] event_json_object["signatures"] = signed_json_oject["signatures"]
return event_json_object return event_json_object
Servers can then transmit the entire event or the event with the non-essential Servers can then transmit the entire event or the event with the non-essential
keys removed. Receiving servers can then check the entire event if it is keys removed. If the entire event is present, receiving servers can then check
present by computing the SHA-256 of the event excluding the ``hash`` object, or the event by computing the SHA-256 of the event, excluding the ``hash`` object.
by using the ``hash`` object included in the event if keys have been redacted. If the keys have been redacted, then the ``hash`` object is included when
calculating the SHA-256 instead.
New hash functions can be introduced by adding additional keys to the ``hash`` New hash functions can be introduced by adding additional keys to the ``hash``
object. Since the ``hash`` object cannot be redacted a server shouldn't allow object. Since the ``hash`` object cannot be redacted a server shouldn't allow

Loading…
Cancel
Save