Skip to content

Canonicalization

All INK messages are canonicalized using JSON Canonicalization Scheme (JCS, RFC 8785) before signing. This ensures deterministic byte-level representation regardless of JSON serialization order.

Procedure

Implementations MUST:

  1. Serialize the message body (excluding the signature field itself) using JCS.
  2. Construct the signature base by joining six fields with \n: PROTOCOL + "\n" + METHOD + "\n" + PATH + "\n" + recipientDid + "\n" + JCS(body) + "\n" + timestamp, where PROTOCOL is the message’s signed protocol value, ink/0.1 by default or a negotiated ink/0.2.
  3. Sign the resulting byte string with the sender’s Ed25519 private key.

Omitting the PROTOCOL line is the most common implementation bug: signatures from a five-field base will not verify against a six-field one. See Authentication for the full anatomy.

Why JCS

SSB’s original design used JSON.stringify with specific key ordering, which caused interoperability bugs across implementations. JCS (RFC 8785) is a proper IETF standard that defines canonical JSON serialization unambiguously.

Key JCS rules:

  • Object keys sorted lexicographically by code point
  • No whitespace between tokens
  • Numbers serialized per ECMAScript Number.toString()
  • Strings escaped per JSON spec with no unnecessary escaping