Skip to content
↑↓ to move · Enter to openEsc to close
Glossary · Cryptography

RFC 8785 (JCS): one exact byte form for signed JSON

Updated

Signatures work on bytes, and JSON can express the same data many ways: member order, spacing, escapes and number formats all vary between libraries. Without a canonical form, a verifier could compute different bytes from the signer and reject a valid signature, or two parties could disagree about what was signed.

JCS removes that ambiguity. It is published by the IETF as RFC 8785.

Definition

RFC 8785, the JSON Canonicalization Scheme (JCS), defines one exact byte serialization for any JSON value, with sorted members, fixed number formatting and no insignificant whitespace. AgenID canonicalizes every hashed or signed object with it.

Also known as: JCS, JSON Canonicalization Scheme

How it works in AgenID

Canonicalization runs on a parsed data structure, never by patching serialized text. Members are sorted by UTF-16 code units, non-ASCII text is emitted as raw UTF-8, strings escape only quotation marks, backslashes and control characters, and numbers follow ECMAScript formatting, so 1.0 becomes 1. AgenID adds one rule: NaN, infinity and integer literals above 2^53 minus 1 are rejected as invalid_number_domain, and no schema field is a number at all. The canonical bytes feed both the manifest digest and the Ed25519 signing input.

Why it matters

It is what makes a signature independently re-verifiable. The specification publishes adversarial vectors for numbers, Unicode, sort order and empty values; the browser signer at /issue uses its own independent JCS implementation; and the public conformance suite lets any other implementation check itself.

Without JCS, an innocent difference such as one library writing 1.0 where another writes 1 would change the bytes and break the signature. With it, a verifier in any language reconstructs the exact input the signer used, which is the precondition for checking anything offline.

What it does not mean

Canonical bytes make agreement about what was signed possible; they say nothing about whether it is true. Canonicalization is also not a permission mechanism: it fixes what a statement says, not what an agent is allowed to do. Nor is it encryption: canonical JSON is readable by anyone.

Frequently asked questions

Is JCS the same as sorting keys before JSON.stringify?

No. Sorting alone misses number formatting, string escaping and UTF-16 ordering, which is where implementations diverge.

Is the signature member canonicalized too?

No. signature is removed first. Including it in the input is a verification failure.

Where are AgenID's canonicalization test vectors?

In section 8 of the public specification. You can also check a live agent at /verify.

What agenid.com issues today

The reference deployment at agenid.com issues DECLARED and L1_REGISTERED only. L2_DOMAIN_VERIFIED and higher require a VerificationAssertion signed by a root authority key, and that key has not been created yet. L5 is reserved by the specification and is not issuable at all.

Identity is not permission

Which agent is acting and who declared it is one question. What that agent is allowed to do is another, and it stays with the party on the other side and with the operator. Protocol v1.1.1 defines no signed authorization object.

Sources

  1. RFC 8785: JSON Canonicalization Scheme (JCS)
  2. AgenID protocol specification (public repository)

Give your agent an identity

Register an agent in the browser — the signing key is generated on your device and never sent to AgenID — or resolve an existing AgenID and re-check its signature yourself.