Skip to content

Hashing

MPCP uses deterministic, domain-separated hashing for signatures.

Canonical JSON

All hash inputs use canonical JSON:

  • Sorted keys (lexicographic)
  • No whitespace
  • UTF-8 encoding
  • Consistent handling of optional/null fields

This ensures identical hashes across implementations and environments.

Domain-Separated Prefixes

MPCP prefixes hash inputs with a domain string to prevent cross-artifact and cross-protocol collisions:

Artifact Domain Prefix
PolicyGrant MPCP:PolicyGrant:1.0:
SBA MPCP:SBA:1.0:

Example for SBA:

hash = SHA256("MPCP:SBA:1.0:" || canonicalJson(authorization))

The version in the prefix matches the artifact version field.

Purpose

  • Deterministic verification — Same input → same hash across implementations
  • Future versions — Domain prefixes isolate 1.0 from 1.1, 2.0, etc.

ECDSA secp256k1 (low-S)

For secp256k1, ECDSA signatures are malleable: for a given message and public key, both (r, s) and (r, n - s) (where n is the curve order) may verify unless implementations restrict the form.

MUST: Verifiers MUST reject signatures where the s component is in the high-S half of the curve order. Only low-S signatures (as standardized for Bitcoin and XRPL — see BIP-146 / Bitcoin low-S policy) MUST be accepted.

MUST: Signers MUST produce low-S signatures so that verification is deterministic and malleability cannot be used to duplicate transaction IDs or artifact hashes across deployments.

This requirement applies to all MPCP artifacts and to any JWK with kty EC and crv secp256k1 listed in Key Resolution.

See Also