| Internet-Draft | COSE_Sign1 Framing Space | September 2026 |
| Templeman | Expires 9 March 2027 | [Page] |
A signed statement conveyed as a COSE_Sign1 object may be serialized into many distinct byte sequences that all decode to the same data item. Where a protocol identifies such a statement by a digest computed over its wire octets (referred to here as a data-hash), the identifier is sensitive to that framing while the signature over the statement is not.¶
This document reports a measurement of the size of that class. Taking one 165-octet COSE_Sign1 object and re-emitting it under every combination of six CBOR encoding freedoms yields 64 distinct octet sequences. All 64 carry an identical Sig_structure and therefore an identical, valid signature. All 64 produce distinct data-hash values, with no collisions. A stock CBOR decoder rejected none of them, and 31 were silently repaired into the canonical form by the act of being read.¶
This document specifies nothing and proposes no wording. It reports a measurement, publishes the reproduction recipe, and identifies the prior work that already addresses the problem it measures.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 9 March 2027.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
Transparency protocols in the SCITT architecture [RFC9943] frequently need a stable identifier for a signed statement. A natural choice is a digest over the octets of the statement as it appeared on the wire, since that is what a client fetches and can byte-compare. This document refers to such a digest as a data-hash.¶
Identifiers of this shape appear in the SCITT Reference APIs [I-D.ietf-scitt-scrapi] and in the CCF profile for COSE receipts [I-D.ietf-scitt-receipts-ccf-profile]. The measurement reported here is offered as input to that work rather than as a comment on either document.¶
CBOR [RFC8949] permits a single data item to be encoded in more than one way. A COSE_Sign1 object [RFC9052] may be emitted with or without its tag, with definite or indefinite length arrays and maps, and with byte strings emitted whole or in chunks. Each such choice changes the octets without changing the decoded value.¶
The signature does not observe those choices. Per [RFC9052], Section 4.4, the Sig_structure covers the protected header and the payload; it does not cover the framing of the enclosing container. The consequence is an asymmetry: two parties may agree that a signature is valid and still disagree on the data-hash of the statement they have both just verified.¶
Two instances of this asymmetry were raised independently on the SCITT mailing list within two days of each other in September 2026: one concerning the CBOR tag, one concerning the outer array. That coincidence prompted the question this document answers: not "which framings exist", but "how large is the class they belong to".¶
This document is Informational and contains no normative requirements.¶
A single COSE_Sign1 object, referred to here as A, was taken as the
starting point. A is 165 octets and has the SHA-256 digest
8595e4a4c8b93e7b1b7b798dc302a2b7d2890021f7eff372d79b32f78867e4ac.¶
A was decoded once, and the resulting data item re-emitted under every combination of six independent encoding freedoms:¶
Six binary freedoms give 64 combinations. No element value was altered at any point; only its encoding. Each resulting octet sequence was then decoded with a stock CBOR decoder, and both its data-hash and its Sig_structure were computed.¶
The decoder used was cbor2 6.1.3 on CPython 3.13, macOS arm64. The measurement, its inputs and the minting script are published at https://councilof.ai/interop/scrapi-ccf/data-hash-framing-space.json.¶
| Quantity | Value |
|---|---|
| Encoding freedoms varied | 6 |
| Distinct octet sequences produced | 64 |
| Distinct data-hash values | 64 |
| Data-hash collisions | 0 |
| Rejected by the stock decoder | 0 |
| Silently re-serialized to A on read | 31 |
| Distinct Sig_structures across all 64 | 1 |
The last two rows carry the substance of the result.¶
There is exactly one Sig_structure across all 64 encodings: 109 octets, with
the SHA-256 digest
60b4c76b84c456ed0604305075f51f6d050476177ef17be70a13a7b9abfb370f.
A single signature therefore verifies over every one of the 64 encodings,
while each of those encodings has a different data-hash.¶
Of the 64, 31 were repaired into the canonical form by the act of being read: a decode-then-re-encode cycle returned exactly A's octets. An implementation that stores a re-serialization of what it received, rather than the received octets themselves, will therefore compute a data-hash it cannot later reproduce from what it published, and no error is raised at any point in that sequence.¶
The 64 encodings ranged from 164 to 170 octets. The smallest, at 164 octets, is A with the tag removed; it is the one variant of the seven named in the published artifact that does not re-serialize to A.¶
This measurement does not vary integer-width encoding or map key ordering. The true class is therefore larger than 64.¶
The observation this document supports is narrow: a rule that enumerates disallowed framings cannot close a combinatorial class, because the class is larger than the set of framings anyone has happened to notice. Two axes were found by accident in one week; six freedoms give 64 encodings; and the six tested are not all of them.¶
This document does not propose that data-hash be made framing-invariant. The wire octets are what a client fetches and byte-compares, so hashing them is the appropriate choice. The open question is only which octets are meant.¶
A consequence worth stating explicitly, because it is an implementation requirement rather than a wording question: a service that publishes a data-hash cannot reproduce the identifier it published unless it retains the octets it received rather than a re-serialization of them. The figure of 31 silent repairs out of 64 indicates that a decode-and-re-encode storage path will encounter this in practice rather than in theory.¶
This document discovers nothing. It measures the size of a class whose members were identified by others, and the approaches that address it were published before this measurement was made.¶
[I-D.mih-sokolov-scitt-payload-binding] registers an
as-transmitted binding, under which no canonicalization is applied
and the pre-image is the exact octet sequence, and withdrew two
canonicalization profiles before it. That approach closes the whole class
measured here, and predates this measurement.¶
The outer-array framing axis was raised on the SCITT mailing list on 2026-09-04 by Konrad Gruszka, together with an independent recomputation performed on a different platform with a different reader and no COSE library. The tag axis was raised on the list on 2026-09-03 by the author of this document. The tag axis surfaced only because Emek Can Dogru recomputed a previously published vector rather than reading it.¶
This document is offered because the measurement is reproducible and the magnitude may be useful to those weighing the alternatives, not because the alternatives are in doubt.¶
The behaviour reported here is a naming and reproducibility hazard rather than a break of any cryptographic primitive. No signature is forged, no digest is collided, and the signature scheme behaves exactly as [RFC9052] specifies.¶
The hazard is that a verifier and an issuer may both be correct and still disagree. Where a data-hash is used as a lookup key, an index, a deduplication key, or as the subject of a further attestation, an adversary able to influence the framing of a statement in transit, without invalidating its signature, can cause that statement to be filed under an identifier the issuer does not expect, or to appear absent from a service that in fact holds it.¶
Retaining received octets verbatim, as [I-D.mih-sokolov-scitt-payload-binding] describes, removes this class of hazard. Enumerating individual disallowed framings does not, since the enumeration cannot be shown to be complete.¶
This document has no IANA actions.¶
The published artifact contains the starting object A, the seven named variants with their sizes and digests, the full finding, and the script that mints them:¶
The starting object A is field
A_signed_statement_as_registered.bytes_hex of the second file. Its
SHA-256 is recorded in the first. Re-emitting it under the six freedoms
listed in Section 3 and hashing each result reproduces the
table in Section 4.¶
Konrad Gruszka raised the outer-array framing axis and independently recomputed the vector on a separate platform. Emek Can Dogru recomputed a published vector rather than reading it, which is what surfaced the tag axis. Anton Sokolov's registration of an as-transmitted binding reached the conclusion this measurement supports before the measurement was made.¶