Hash exactly what you declare — byte-for-byte, line-for-line
What this subsection establishes (in one line).
A sender declares the precise fields that are committed by the digest and then binds those exact bytes (and optionally the raw body) to a stamp, so any receiver can recompute the same sha256 without coordination or trust.
Subset declaration (on the wire).
The sender names the fields and their order; only these bytes are bound by the digest.
# canonical subset (example) subset := ["value","band","manifest_id"] # optionally include "align_ascii" if declared public HEAD := SHA256( serialize(subset_fields) [+ raw_body_bytes_if_declared] )
Serialization rules (normative).
These rules make independent recomputation deterministic:
# text encoding - All textual subset fields MUST be UTF-8 in NFC normalization (no BOM). # newlines - Newline is LF only: "\n". Before hashing, normalize all line endings in subset fields to "\n". # field order - Serialize fields exactly in the declared order from `subset`. No extra fields; none omitted. # whitespace & formatting - Spacing, quoting, and separators MUST be stable per the active profile’s canonical form. # numbers as text - Any numeric committed as text MUST be deterministic. Example: align_ascii uses fixed sign and fixed decimals: "+0.732000" # escaping - Strings use a single profile-defined escape scheme; no alternate equivalent encodings. # binary fields - If a subset field is binary, commit its raw bytes (not a re-encoded textual form). # optional per-line trim - If TRIM_WHITESPACE_PER_LINE is enabled by manifest/profile: - After converting to LF, trim leading/trailing ASCII space (0x20) and tab (0x09) on each line. - Do NOT alter interior spaces. Do NOT apply to binary fields.
Body commitment (when a body exists).
Hash the actual on-the-wire body bytes (post any transport encoding such as compression).
# body binding (if declared) raw_body_bytes := EXACT_BYTES_SENT_ON_WIRE BODY_HEAD := SHA256(raw_body_bytes) HEAD := SHA256( serialize(subset_fields) + raw_body_bytes )
Expose the body commitment alongside the subset declaration so receivers can recompute identically.
Norms for participants.
# sender MUST - Expose the subset declaration and keep its serialization stable. - Hash byte-exactly the declared fields (and body if declared). # receiver MUST - Recompute SHA256 over the same byte sequence and compare equality (no tolerance). - Treat hidden/missing/misordered fields as verification failure. # stability rule - Pretty-printing or whitespace changes OUTSIDE the declared subset MUST NOT affect verification.
Failure patterns (illustrative).
- Re-serializing fields in a different key order than declared in `subset`. - Changing numeric formatting of align_ascii (e.g., omitting sign or decimals). - Hashing decoded body bytes instead of the exact on-the-wire (e.g., hashing uncompressed text when wire carried gzip). - Enabling TRIM_WHITESPACE_PER_LINE but trimming characters other than space/tab. - Emitting CRLFs in subset serialization instead of LF.
Why it matters (human terms).
By committing exact bytes you declared, you remove ambiguity from provenance disputes. Anyone can rerun the hash and arrive at the same HEAD—no screenshots, no vendor-specific parsers, no “nearly the same” encodings.
Navigation
Previous: SSM-NET — Bands & Envelope (2B–2C)
Next: SSM-NET — Continuity stamp (2E)