json-signing.md 2.5 KB

JSON Data Signing

As serializing and deserializing JSON is not deterministic, but may depend on the order in which keys are added or even the system's collation method, signing JSON cryptographically is fraught with issues. We circumvent them by wrapping any JSON to be signed in another JSON object:

  • version contains the version of the wrapper JSON, currently always 1.
  • serialized contains the serialized version of the data, currently this will be the base64 encoded, serialized JSON payload.
  • signature contains the base64 encoded signature of the serialized field value prior to its base64 encoding.
  • payload [optional] contains the deserialized JSON object corresponding to the serialized payload.

For signing and verification, we'll use polkadot's ed25519 or sr25519 keys directly.

Signing Process

Given some structured data:

  1. Serialize the structured data into a JSON string.
  2. Create a signature over the serialized JSON string.
  3. Create a new structured data with the appropriate version field.
  4. Add a base64 encoded version of the serialized JSON string as the serialized field.
  5. Add a base64 encoded version of the signature as the signature field.
  6. Optionally add the original structured data as the payload field.

Verification Process

  1. Verify data contains a version, serialized and signature field.
  2. Currently, verify that the version field's value is 1.
  3. Try to base64 decode the serialized and signature fields.
  4. Verify that the decoded signature is valid for the decoded serialized field.
  5. JSON deserialize the decoded serialized field.
  6. Add the resulting structured data as the payload field, and return the modified object.

Alternatives

There are alternative schemes available for signing JSON objects, but they have specific issues we'd like to avoid.

  • JOSE has no support for the ed25519 or sr25519 keys used in polkadot apps, and appears to be fraught with security issues. Either makes its use hard to justify.
  • While PASETO does use ed25519 keys and seems to have a reasonably robuts JavaScript implementation, it requires its secret keys to be 512 bits long, while polkadot provides 256 bit secret keys. The implication is that we would have to manage 512 bit keys and their corresponding public keys as linked to polkadot's keys, which is cumbersome at the very least.