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:
- Serialize the message body (excluding the
signaturefield itself) using JCS. - Construct the signature base by joining six fields with
\n:PROTOCOL + "\n" + METHOD + "\n" + PATH + "\n" + recipientDid + "\n" + JCS(body) + "\n" + timestamp, wherePROTOCOLis the message’s signedprotocolvalue,ink/0.1by default or a negotiatedink/0.2. - 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