| Internet-Draft | Evaluation Receipt Mappings | October 2026 |
| Gruszka | Expires 13 April 2027 | [Page] |
A Signed Evaluation Receipt records one evaluation result as signed payload bytes B. This document describes how existing envelopes cite such a receipt by the SHA-256 digest of B, and how a DSSE envelope carries B with the receipt's own signature. It fixes those bytes and a matching rule, maps the parts of a receipt onto DSSE, the in-toto Statement with the test-result predicate and the SLSA Verification Summary Attestation, shows that the signature of a receipt is already a valid DSSE signature, gives an example of a SCITT Signed Statement that names a receipt only by its digest, declares the receipt digest as an artifact type for typed digest references, and relates a receipt to a pre-run criteria set written in PRML. It defines no new format and no new predicate.¶
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 13 April 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.¶
A Signed Evaluation Receipt (receipt) [RECEIPTS] holds one assertion, whether a threshold held for a metric of a test suite, as payload bytes B. B is signed with Ed25519 over a pre-authentication encoding with a fixed type. A receipt carries no inclusion proof and does not prove registration with a Transparency Service. In SCITT, transparency additionally requires registering a Signed Statement that names the receipt and verifying the resulting SCITT Receipt (Section 5).¶
Other parties will want to refer to a receipt from the envelopes they already use: a DSSE envelope, an in-toto Statement, a SLSA Verification Summary, or a SCITT Signed Statement. This document is the third part of one line of work: [STATEMENT-ID] asks how a signed statement is named unambiguously, [RECEIPTS] fixes the bytes of a receipt, and this document shows how existing envelopes cite such a receipt by digest.¶
It also relates a receipt to a criteria set fixed before the run in PRML [PRML] (Section 6), and says where it meets the requirements of [ABAK] for exchanging evaluation evidence (Section 7).¶
This document defines no second receipt format, no new in-toto predicate and no new COSE header parameter. What a receipt does not prove stays unproven when an envelope cites it (Section 8).¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
The terms receipt, B, Issuer, Receiver and type are used as in [RECEIPTS]. The type is the fixed string¶
application/vnd.signed-evidence.eval-receipt+json¶
The type identifies B ([RECEIPTS] Section 10.1). The receipt object uses the same fixed string as its schema discriminator, but is a different JSON representation.¶
A hash algorithm and a digest value that an envelope carries to name a receipt.¶
An in-toto Statement or a COSE Signed Statement that carries a citation. A DSSE envelope carries B itself, not a citation (Section 4.1).¶
The receipt digest is SHA-256 over B, the payload bytes of the receipt as
defined in [RECEIPTS] Section 3.4: the bytes that steps 1 to 3 of
[RECEIPTS] Section 5 obtain from payload_b64. A candidate for which one of
those steps fails has no B, even if a lenient decoder would produce bytes from
it (cases C6 and C7). It is not computed over the receipt bytes or over
PAE(type, B). An envelope that carries the
digest as text uses its 64 lowercase hexadecimal digits; one that carries it as
bytes uses the 32 bytes. This document defines no other hash algorithm.¶
The digest runs over B for two reasons.¶
B is what is signed. The signing input PAE(type, B) depends on B alone, because the type is fixed ([RECEIPTS] Section 4.2). A digest over B therefore names exactly the signed content; a digest over the signing input would carry no further information.¶
The receipt bytes are not stable. The receipt object around B is not canonicalized, and its key hint is not signed. Vectors P1, P4 and P6 of [RECEIPTS] are three different receipt byte strings that all verify and all carry the same B (cases C1 to C3 of Table 1). A digest over the receipt bytes would give one signed statement three names, and it would change whenever the receipt object is written again. In-toto resource descriptors and the COSE Hash Envelope each name content by the digest of its bytes, and a DSSE envelope carries the bytes themselves.¶
The price of this choice: the receipt digest identifies the signed content, not
the signature and not the key. Two receipts with the same B under different
keys have the same digest. The iss and kid of a citing Signed Statement
(Section 5.2) identify its signer, which need not be the receipt
signer. This mapping does not encode a constraint on the receipt signer. A
Receiver verifies the cited receipt under the receipt key it fixed
independently.¶
Given a citation and a candidate receipt, the result is computed as follows.¶
If the citation's algorithm is not SHA-256, or its value is not 32 bytes (64
lowercase hexadecimal digits in text form), the result is INDETERMINATE.
SHA-256 is named sha256 as the key of an in-toto digest set [INTOTO-DIGESTSET], -16 as the
value of COSE header parameter 258, and sha-256 as the algorithm label of
the examples (Appendix A); each name counts only in its own carrier, and
names are compared exactly, so SHA256 is none of them. A typed digest
reference names it SHA-256 (Section 5.1). A digest set with several
entries is matched on its sha256 entry alone; this document does not judge
the other entries. This is narrower than the matching guidance of
[INTOTO-DIGESTSET], under which two digest sets match if any acceptable
field matches: here a digest set without a sha256 entry gives
INDETERMINATE, and one whose sha256 entry passes step 1 but differs from
SHA-256 over B gives NO_MATCH, whatever its other entries are.¶
If steps 1 through 3 of [RECEIPTS] Section 5 do not all complete successfully, including when processing stops at a resource limit, B is not obtained and the result is INDETERMINATE.¶
Otherwise the result is MATCH when SHA-256 over B equals the cited value, and NO_MATCH when it does not.¶
A MATCH establishes neither that the candidate verifies, nor who signed it, nor that its assertion is true. A Receiver that relies on a cited receipt runs the full procedure of [RECEIPTS] Section 5 under a key it fixed. Case C5 is a candidate that matches and fails that procedure at step 11.¶
| Case | Candidate | Result | Verification of the candidate | What it shows |
|---|---|---|---|---|
| C1 | P1 | MATCH | PASS | the receipt the citation was made from |
| C2 | P4 | MATCH | PASS | other receipt bytes (an escaped character in schema), same B |
| C3 | P6 | MATCH | PASS | other receipt bytes (no key hint), same B |
| C4 | P2 | NO_MATCH | PASS | another receipt with another B |
| C5 | N7 | MATCH | FAIL, step 11 (profile 4) | same B, signature made over another type: a match is not a verification |
| C6 | N13 | INDETERMINATE | FAIL, step 3 | payload_b64 is not canonical base64: B is not obtained |
| C7 | N14 | INDETERMINATE | FAIL, step 1 | the receipt has duplicate member names: B is not obtained |
| C8 | P1 | INDETERMINATE | PASS | the citation names an algorithm this document does not define |
[STATEMENT-ID] proposes requirements A1 to A5 for references to signed statements. This section checks the receipt digest against them. It is the author's analysis, not a conformance claim; no registration in a Transparency Service is measured.¶
The scheme names the hash algorithm (SHA-256), the input bytes (B, as steps 1 to
3 of [RECEIPTS] Section 5 obtain it from payload_b64) and the encoding (64 lowercase hexadecimal digits or 32
bytes). Section 3.3 is the matching rule. An unsupported algorithm or a
candidate without B gives INDETERMINATE, never MATCH (C6 to C8). Identity is
preserved under every difference outside B that leaves steps 1 to 3 of
[RECEIPTS] Section 5 succeeding: the receipt's whitespace and
escapes, its key hint, and its signature value. In the
terms of [STATEMENT-ID] Section 5 the receipt digest is a digest of the
payload. Because the type is fixed and nothing else enters the signature, it
also determines the signing input; neither names the signer.¶
In the COSE Hash Envelope of Section 5.2 the citation is read from header parameters 258 and 259 and the payload, as [RFC9995] defines them, without interpreting application content. In an in-toto Statement the citation lies inside the predicate, which is the Statement's application content; a reader has to know the predicate to find it. A2 is met by the first and not by the second.¶
B does not change when the receipt is registered anywhere or its object is written again. Cases C2 and C3 carry other receipt bytes and still match.¶
Cases C2 and C3 apply local changes that a re-encoding may cause (another JSON escape, a key hint left out), and the result stays MATCH. This is not a measurement of registration in two services.¶
Matching does not depend on a leaf hash or a COSE Receipt. A receipt has no inclusion proof of its own; a Transparency Service that registers a statement naming it fixes its own leaf construction, and matching does not use it.¶
Table 2 shows, for each part of a receipt, where it has a place in three envelopes and what that envelope does not have: DSSE [DSSE], the in-toto Statement v1 [INTOTO-STATEMENT] with the test-result predicate v0.1 [TEST-RESULT] (test-result in the table), and the SLSA Verification Summary Attestation v1 [VSA] (VSA). "None" means that the envelope has no field for it. This document defines no predicate of its own.¶
| Receipt part | Envelope | Field there, or what is missing |
|---|---|---|
| B | DSSE |
payload, base64 of B |
| test-result | none; a Statement that restates the members is other bytes | |
| VSA | none; inputAttestations[].digest names B by its digest |
|
| type | DSSE |
payloadType
|
| test-result | none; the Statement's envelope carries an in-toto type | |
| VSA |
inputAttestations[].mediaType
|
|
signature.sig
|
DSSE |
signatures[].sig, the same bytes (vector M1) |
| test-result | none; the Statement's envelope carries a new signature | |
| VSA | none; the VSA is signed by its verifier | |
signature.alg
|
DSSE | none; DSSE names no signature algorithm |
| test-result, VSA | none | |
signature.key
|
DSSE |
keyid, optional and not signed |
| test-result, VSA | none | |
passed
|
DSSE | inside B |
| test-result |
result PASSED or FAILED; WARNED has no receipt counterpart |
|
| VSA | none; verificationResult is the verifier's result |
|
payload schema
|
DSSE | inside B |
| test-result | none; predicateType names test-result, not the payload schema |
|
| VSA | none | |
suite, suite_version
|
DSSE | inside B |
| test-result | no field of its own; configuration or url can name the suite |
|
| VSA | none | |
metric, comparator, threshold, score, n
|
DSSE | inside B |
| test-result, VSA | none | |
criteria_digest, when present |
DSSE | inside B |
| test-result, VSA | none | |
model_id_commit, dataset_id_commit, commit_alg
|
DSSE | inside B |
| test-result | none; subject wants a digest of the artifact, and a commitment is not one |
|
| VSA | none; subject and resourceUri name the verified artifact |
|
timestamp
|
DSSE | inside B |
| test-result | none | |
| VSA | none; timeVerified is the verifier's time |
In the other direction, a receipt has no counterpart for the required VSA
fields verifier, resourceUri, policy and verifiedLevels, for its
optional timeVerified, or for the subject of an in-toto Statement.¶
The signature of a receipt is a valid DSSE signature without any new signature. DSSE [DSSE] signs PAE(payloadType, payload) with the same pre-authentication encoding that [RECEIPTS] Section 4.1 defines. The envelope¶
{"payloadType": <type>, "payload": <base64 of B>,
"signatures": [{"sig": <the receipt's signature.sig>}]}
¶
therefore verifies as DSSE under the Issuer's key when payloadType is exactly
the type and payload decodes to B. Vector M1 (Appendix A) gives the bytes;
its signature is the signature of vector P1 of [RECEIPTS], byte for byte. M1
leaves out keyid, which DSSE treats as an optional, unauthenticated hint.¶
A successful DSSE signature check alone is not a receipt verdict. DSSE also
requires a supported payloadType and parsing the authenticated payload
according to that type. To obtain a receipt verdict, a Receiver decodes the
payload and the selected signature once, uses those same bytes to construct the
receipt object with canonical base64 as required by [RECEIPTS] Section 3.1,
and runs [RECEIPTS] Section 5 under its independently selected receipt
verification key.¶
The signature is expected to be valid as DSSE only under this payloadType,
because Ed25519 binds the exact signing input; this is not measured beyond
sample types. Vector N7 of [RECEIPTS] shows the converse for the receipt
itself: its signature, made over PAE with the type
application/vnd.example.other+json, fails under the fixed type.¶
The test-result predicate [TEST-RESULT] records result (PASSED, WARNED or
FAILED), configuration (a required list of resource descriptors), url, and
the lists passedTests, warnedTests and failedTests. A Statement
[INTOTO-STATEMENT] that restates a receipt maps passed to result PASSED
or FAILED. No member of the predicate carries the metric, the comparator, the
threshold, the score, the sample count or the timestamp; passedTests and
failedTests are lists of test names, not a count. The Statement's subject
names the tested artifact by digest; a commitment is not a digest of the
artifact's bytes, so the model commitment cannot stand as subject without
changing what subject means.¶
Such a Statement is a new statement by whoever signs its envelope [INTOTO-ENVELOPE]. It does not carry the receipt's signature and the predicate has no member for the evidence a result rests on. This document therefore does not cite receipts from test-result; the mapping states what a party loses when it restates a receipt in that form.¶
A Verification Summary Attestation [VSA] states that a verifier verified an
artifact against a policy. Its inputAttestations is a list of resource
descriptors [INTOTO-RD], each of which carries a digest of the attestation it names. A
verifier that used a receipt as evidence when it verified an artifact, for
example the evaluated model, and verified the receipt under [RECEIPTS]
Section 5, cites the receipt there; the artifact itself is the VSA's
subject:¶
{"digest": {"sha256": "<receipt digest, 64 hex digits>"},
"mediaType": "application/vnd.signed-evidence.eval-receipt+json"}
¶
The mediaType identifies B. verificationResult
is the verifier's result under its policy, not the receipt's passed: a
receipt that verifies and records passed false (vector P2 of [RECEIPTS])
can be the input of a VSA whose verificationResult is PASSED, when the
verifier's policy asks only for a valid receipt.¶
A Signed Evaluation Receipt is not a COSE Receipt. Its format is JSON with Ed25519 over PAE, not COSE; it carries no inclusion proof, and no Transparency Service or Registration Policy [RFC9943] takes part in making it. In SCITT, a Transparency Service registers a Signed Statement and returns a COSE Receipt [RFC9942] proving its inclusion.¶
Two existing constructions carry the receipt digest without a new field: a typed digest reference (Section 5.1) and a Signed Statement whose payload is the digest (Section 5.2). Both name the receipt; neither carries it.¶
[CPB] Section 8 defines a typed digest reference with the members type,
purpose, digest_alg and digest, and leaves the declaration of artifact
types to the profiles that accept them ([CPB] Section 8.1). This document
declares one artifact type for the receipt digest:¶
type is application/vnd.signed-evidence.eval-receipt+json, the type,
which identifies B;¶
there is one digest context, so purpose is absent;¶
the canonicalization algorithm is as-transmitted ([CPB] Section 4.4),
with the byte-boundary selector [RECEIPTS] Section 3.4, "The Bytes B";¶
the hash function is SHA-256, and digest_alg is exactly SHA-256;¶
digest is the receipt digest as its 64 lowercase hexadecimal digits, a
text value; in the cpb-refs header parameter of [CPB] Section 8.3 it is
a text string.¶
A reference under this declaration can stand in the cpb-refs header
parameter of a Signed Statement, or in a payload that carries references in
its own serialization, for example in the references of [CAPSULE]. A
verifier obtains B by steps 1 to 3 of [RECEIPTS] Section 5, computes
SHA-256 over it and compares the hexadecimal text. A candidate without B
cannot be obtained as the cited artifact, which [CPB] Section 8.1 calls
Unresolved; it corresponds to INDETERMINATE in Section 3.3. A consuming
profile that does not name this declaration by normative reference leaves
every such reference Unresolved ([CPB] Section 8.1); no profile names it at
the time of writing.¶
Only the digest crosses, as for the Signed Statement below. A reference that is Verified shows that the cited bytes are B; it does not show that the receipt verifies, who signed it, or that its assertion is true ([CPB] Section 8.5).¶
A Signed Statement that cites a receipt is a COSE_Sign1 [RFC9052] with CBOR tag 18 in the form of a COSE Hash Envelope [RFC9995]. Its form is fixed, so that one receipt digest, one statement key, one issuer and one algorithm value give one byte string. Vector M2 (Appendix A) is such a statement.¶
The protected header holds exactly these five parameters and no other:¶
1 (alg): -19, Ed25519 as fully specified in [RFC9864], or -8, EdDSA [RFC9053]. A party that makes a statement MUST write -19. A Receiver MUST accept both values and applies every other check of Section 5.2.2 to either; under the Ed25519 statement keys that step 3 selects, both values select the same signature algorithm. Changing alg changes the protected header bytes and requires a new signature (Section 5.2.4);¶
4 (kid): the COSE Key Thumbprint [RFC9679] with SHA-256 of the statement
key, a byte string of 32 bytes. For an Ed25519 public key x, kid is SHA-256
over the core-deterministically encoded COSE_Key map {1: 1, -1: 6, -2: x};
no optional COSE_Key parameter enters the thumbprint;¶
15 (CWT Claims) [RFC9597]: a map with exactly 1 (iss), an absolute URI
([RFC3986] Section 4.3) that names the party that makes the statement, and
2 (sub), the text value of model_id_commit of B;¶
258 (payload hash algorithm): -16 (SHA-256);¶
259 (preimage content type): the type, as a text string.¶
The unprotected header is the empty map.¶
The payload is the receipt digest, 32 bytes.¶
The COSE_Sign1, its protected header included, is encoded with the core deterministic encoding of [RFC8949] Section 4.2.1.¶
The value of sub is a choice of this example; the receipt digest does not
depend on it. The statement key and the receipt key can be the same key or
different keys. The statement carries its own signature over its own
Sig_structure; it is not the receipt's signature, even when one key makes both.
Registering M2 with a Transparency Service yields a COSE Receipt for M2, not
for the evaluation receipt.¶
A party makes a statement for a receipt only after the receipt has passed the
verification procedure of [RECEIPTS] Section 5 under a key that party fixed.
A receipt that fails it gives no statement. The party computes the receipt
digest over B, takes sub from the model_id_commit of B, writes the
protected header above, signs the Sig_structure of [RFC9052] Section 4.4 with
an empty external_aad under the statement key, and encodes the COSE_Sign1.¶
The Receiver holds the statement, a candidate receipt, its independently selected receipt verification key, and configured pairs of an issuer URI and an Ed25519 statement key. The received iss value does not establish that association. It applies the following steps in order. The first step that fails gives the status named in it, and the statement is refused; only a statement that passes every step is accepted. A Receiver that stops because it reached a resource limit, in any step, reports a resource-limit error; that is no status, and the statement is not accepted.¶
If the bytes are not one CBOR data item in the deterministic encoding, if the item is not a COSE_Sign1, or if its protected header is not a map in the deterministic encoding, the status is malformed. A data item that is well-formed but not valid under [RFC8949] Section 5.3.1, such as a text string that is not valid UTF-8 or a map with duplicate keys, is malformed; two keys are duplicates only when they are equal under the key equivalence of [RFC8949] Section 5.6.1, so the integer 1 and true are two keys and 0.0 and -0.0 are one. Step 1 does not check whether the content of a tag inside the COSE_Sign1 is valid for that tag ([RFC8949] Section 5.3.2); the data items inside a tag are checked like any other data item. For step 1, the COSE_Sign1 check concerns only the outer tag, the four-element array and its element types: a wrapping in a CBOR tag other than 18 is not a COSE_Sign1 and is malformed, and an otherwise valid COSE_Sign1 without a tag goes on to step 2 and is outside_profile there. The protected-header byte string is decoded as a CBOR map, with the empty byte string treated as an empty map ([RFC9052] Section 3), which fails in step 2. CBOR validity and deterministic encoding are checked before step 2. Header label types are checked only in step 2; a header label that is not one of the five required integer labels gives outside_profile if step 1 succeeds.¶
If the item is not tagged 18, the unprotected header is not empty, the
protected header does not hold exactly the five parameters above with the
types and values given there, the payload is detached or is not 32 bytes,
or the signature is not 64 bytes, the status is outside_profile. sub MUST be
a text string matching sha256: followed by exactly 64 lowercase
hexadecimal digits; otherwise the status is outside_profile. Step 7 then
compares that string byte for byte with model_id_commit of B.¶
A configured pair counts only if its statement key is 32 octets and its point A meets rules 1 and 2 of [RECEIPTS] Section 4.4: A is a canonical encoding of a point of order L. A point of small order or of mixed order does not count. If no configured pair that counts has both an issuer URI exactly equal to iss and a statement key whose SHA-256 COSE Key Thumbprint equals kid, the status is untrusted_key. Subsequent signature verification uses only keys selected by this pairwise match.¶
If the signature does not meet the four rules of [RECEIPTS] Section 4.4 under a key that step 3 selected, with the Sig_structure of [RFC9052] Section 4.4 in place of PAE(type, B) in rule 4, the status is signature_invalid.¶
Run the verification procedure of [RECEIPTS] Section 5 under the Receiver's receipt key. Continue to step 6 only if it returns PASS. If it returns FAIL, the status is receipt_not_verified. If it stops with a resource-limit error, propagate that error and stop without accepting the statement.¶
If the payload is not the receipt digest of the candidate, the status is digest_mismatch.¶
If sub is not the model_id_commit of B, the status is subject_mismatch.¶
If every step passes, the status is accepted.¶
Steps 1 to 4 do not use the receipt. A general COSE verifier that implements the statement's alg value checks the signature under the rules of its own Ed25519 implementation, which can accept a signature that step 4 refuses, for example one whose R is a point of small order. It does not apply steps 5 to 7, and its success does not show that the statement cites a receipt that verifies.¶
| Receipt | Signed Statement |
|---|---|
| B | only its receipt digest, as the payload |
model_id_commit of B |
sub (2) of the CWT Claims |
| the type | parameter 259 |
the other members of B (schema, suite, suite_version, metric, comparator, threshold, score, passed, n, dataset_id_commit, commit_alg, timestamp), including criteria_digest when present |
not carried; named only through the digest |
| the receipt's signature and its key hint | not carried |
| (none) |
iss, kid and alg, the statement of the party that signs it |
A Receiver that relies on the assertion of a receipt needs the receipt itself; the statement only names it.¶
Value -19 is the fully specified Ed25519 identifier of [RFC9864], which sets the polymorphic EdDSA identifier -8 of [RFC9053] to Deprecated. A party that makes a statement therefore writes -19 only. Every Receiver accepts -8 as well, for statements made before a producer moved to -19 and for general COSE verifiers that implement -8 but not -19 (Section 12), so that one statement gives one status. -8 names EdDSA for any curve; step 3 of Section 5.2.2 counts only Ed25519 statement keys, so a statement with -8 under any other key is untrusted_key.¶
The payload follows the pattern of the hash-only mode of [PRML-PROFILE]: the 32 raw octets of a SHA-256, carried as a byte string and not as hexadecimal text. That profile leaves open how a verifier tells such a payload from a full one, and names a COSE header parameter that declares the digest algorithm as one candidate. Header parameters 258 and 259 of [RFC9995], used here, are such a declaration.¶
PRML [PRML] serializes an evaluation claim fixed before the run: a metric, a
comparator, a threshold, a dataset content hash and a seed, in canonical YAML
whose SHA-256 is the manifest hash. A receipt records one result after the run.
A receipt names a criteria set at most through its optional criteria_digest
([RECEIPTS] Section 3.5). When the criteria set is a PRML manifest, the bytes
that PRML fixes for it are its canonical bytes, whose SHA-256 is the manifest
hash, and criteria_digest over them is sha256: followed by the manifest
hash. Table 4 maps the members of a PRML
manifest, version 0.1, onto a receipt.¶
| PRML | Receipt | Lost or changed |
|---|---|---|
version
|
none | which PRML rules apply |
claim_id
|
none | the claim and its amendment chain; only one manifest is named, by criteria_digest
|
created_at
|
none |
timestamp is when the Issuer states the evaluation ran, not when the criteria were written |
metric
|
metric
|
nothing when the string is copied exactly |
comparator
|
comparator
|
== has no counterpart; such a claim has no receipt |
threshold
|
threshold
|
a number becomes a decimal string; the rule below compares values |
dataset.id, dataset.hash
|
dataset_id_commit
|
the content hash; the receipt commits to an identifier with a salt, not to the content |
seed
|
none | the seed |
producer
|
none | the producer; the receipt names no issuer, the Receiver fixes the key |
model
|
model_id_commit
|
the clear identifier; checking an opening requires the salt and identifier |
prior_hash, metric_args, code, notes
|
none | all of them |
| none |
suite, suite_version, score, passed, n, timestamp
|
a manifest has no result |
A Receiver that holds a receipt and a PRML manifest compares them as follows and reports the two results separately.¶
Run the procedure of [RECEIPTS] Section 5 under the Receiver's receipt key. Continue only if it returns PASS. If it returns FAIL, do not perform the comparison. If it stops with a resource-limit error, propagate that error and stop without reporting binding or agreement results.¶
The manifest is canonicalized as [PRML] Section 3 requires, and its manifest hash is computed. A manifest that PRML rejects is not compared.¶
Binding. The result is BOUND when the receipt carries criteria_digest
and it equals sha256: followed by the manifest hash, and UNBOUND
otherwise.¶
Agreement. The result is AGREE when metric is the same string in both,
comparator is the same and is not ==, and the receipt's threshold
and the manifest's threshold are the same decimal number, the manifest's
value read as the decimal that its canonical rendering denotes (so 0.8
in the manifest and 0.800 in the receipt agree, and
0.80000000000000001 in the receipt does not). Otherwise it is DIFFER.¶
BOUND says that the Issuer states this result belongs to that manifest; AGREE says that the two documents state the same metric, comparator and threshold. Neither result shows that the manifest existed before the run, which needs a time-anchored record of the manifest, such as a registration under [PRML-PROFILE], and evidence of when the run began. Neither shows that the dataset with the manifest's content hash was the one evaluated, or that the seed was used.¶
[ABAK] states format-neutral requirements for converting and consuming
evaluation evidence. This document addresses parts of these requirements for
the conversions it describes; the correspondences below are not a conformance
claim. Table 2 and Table 4 name what each envelope or
document loses, in the sense of its requirement R-CP-9.
Section 3.3 gives INDETERMINATE when B cannot be obtained or the algorithm is
unknown, never a match (R-CP-8, R-CP-10). Section 8 keeps the result of a
verifier or of a registration apart from the receipt's passed, and claims no
order of criteria and run (R-CP-5, R-CP-11). It does not meet the requirements
on coverage and attempts (R-CP-6) or on records of a mapping instance
(R-CP-1): a receipt has no field for them, and this document defines none.¶
The list of [RECEIPTS] Section 6 applies unchanged to a cited receipt. It is repeated here word for word; its one cross-reference is written as a reference to Section 5 of [RECEIPTS].¶
Verification establishes that the receipt passes the format, consistency and signature checks in Section 5 of [RECEIPTS] under the Receiver's selected key. It does not establish that the Issuer's claims are true. In particular:¶
The score can be false. The evaluation can be wrong, badly designed or not run at all; the receipt records what the Issuer states.¶
The run need not have been the only run. An Issuer can evaluate many times and record only the run it prefers.¶
The Issuer can lie. A valid signature binds the statement to the key, not to the truth.¶
A receipt does not show that it was published, logged or shown to anyone else. A receipt does not prove registration with a Transparency Service. In SCITT, transparency additionally requires registering a Signed Statement carrying the receipt or its digest with a Transparency Service and verifying the resulting SCITT Receipt. Registration and verification of the resulting SCITT Receipt are outside this document.¶
The receipt bytes are not a stable name for the receipt. Only B is signed; the receipt object around it is not canonicalized, and its key hint can be present or absent. A party that cites a receipt cites SHA-256 over B.¶
A commitment is computationally binding under the collision resistance of SHA-256. A Receiver can check a claimed opening only after receiving the salt and identifier. Hiding depends on keeping an unpredictable salt secret.¶
The timestamp is the Issuer's statement, not a time attested by another party.¶
The receipt says nothing about individual samples: n is the Issuer's
statement, and no sample result is committed or can be disclosed against the
receipt. A sample-level audit is outside this document and is left to a
separate document.¶
A receipt does not show that the threshold was fixed before the run.¶
criteria_digest binds only the Issuer's statement that this result belongs
to the criteria set with that digest. It shows neither that the criteria set
existed before the run nor that the metric, comparator and threshold in it
equal those in the receipt.¶
Even with salt and identifier disclosed, the receipt does not show that the named model or dataset was the one actually evaluated.¶
Each envelope adds what it does not prove:¶
A citation. A MATCH does not show that the candidate verifies, who signed it, or that its assertion is true (case C5). The digest names B; it names neither a signature nor a key.¶
DSSE. A successful DSSE signature check authenticates PAE(type, B) under the
selected key. A receipt verdict additionally requires the verification
profile and all checks of [RECEIPTS] Section 5. The unauthenticated keyid
is only a key-selection hint.¶
in-toto test-result. A Statement that restates a receipt is the statement of
its signer. It does not show that a receipt exists, and its result does not
show that the receipt's passed is true; both are statements.¶
SLSA VSA. A VSA shows that its verifier states that it verified its subject
under its policy, with the cited receipt among its inputs. verificationResult is not passed, and the VSA
does not make the receipt's assertion true. The digest in
inputAttestations names B, not the signature or the key the verifier used.¶
SCITT Signed Statement and COSE Receipt. The Hash Envelope carries only the
digest. Its registration shows that a Transparency Service registered a
statement naming that digest under its Registration Policy. It does not show
that a receipt with that B exists or that it verifies, and sub binds
nothing beyond the commitment it repeats.¶
Typed digest reference. A Verified reference shows that the cited bytes are B, nothing about the signature, the key or the assertion.¶
PRML. BOUND and AGREE (Section 6) do not show that the criteria were fixed before the run.¶
No envelope in this document carries sample data: a receipt commits to no sample result ([RECEIPTS] Section 6), and a citation names only B.¶
This section follows the guidance of [RFC3552]. The attacker can read, create, modify, replay and reorder receipts and citing envelopes, and controls every input except the Receiver's choice of verification key.¶
Collisions. A citation names B only as well as SHA-256 resists collisions and second preimages.¶
Signer not bound. The receipt digest does not name a key. An attacker who signs the same B with its own key produces a receipt that matches every citation of B. It fails verification under the Receiver's key (Section 3.2).¶
Signature reuse across envelopes. By design the signature of a receipt is a
valid DSSE signature under payloadType equal to the type (Section 4.1). A DSSE
consumer that accepts that payloadType holds the B and the signature of a
receipt, and applies [RECEIPTS] Section 5 before it relies on them. Under any other payloadType the signature is
expected to be invalid (Section 4.1). It is not a COSE signature, because COSE signs a Sig_structure and not
PAE.¶
Digest confusion. For one receipt, the receipt digest, the SHA-256 of the
receipt bytes and the SHA-256 of a DSSE envelope are three different values. A
Receiver compares only the receipt digest with a citation. Appendix A lists
the first two for vector P1 and the third for M1. The
type identifies B, but a receipt object carries the same string as its
schema: a Receiver that fetches a receipt object for
a citation takes B from it by steps 1 to 3 of [RECEIPTS] Section 5 and
compares the digest of that B, never the digest of the object.¶
Algorithm. Only SHA-256 is defined. A citation with another algorithm gives INDETERMINATE (case C8), so it cannot be satisfied by a weaker digest.¶
The receipt digest lets anyone who holds a candidate B confirm it. B carries
salted commitments, so B cannot be guessed without them; a party that knows
them can test guesses for the remaining members, such as score and threshold.
A citation registered with a Transparency Service publishes the digest for as
long as that service keeps its log. The sub of M2 repeats the model
commitment of B in clear; registered, it links every receipt and statement
that commit to the same model identifier with the same salt ([RECEIPTS]
Section 9). The same holds for a criteria_digest that a receipt carries.¶
This document has no IANA actions.¶
This section records the status of known implementations at the time of writing, following [RFC7942], and is to be removed before publication.¶
The examples of Appendix A were produced by a generator script whose two runs are byte-identical, and checked by a separate script that re-derives every value of Appendix A from the bytes, including the match result of every case, with its own implementation of steps 1 to 3 of [RECEIPTS] Section 5.¶
An implementation of both directions of Section 5.2, the open-source
package proofbundle (module receipt_cose, experimental), reproduces M2 byte
for byte from vector P1 of [RECEIPTS] and returns each status of
Section 5.2.2 for a set of 49 statements and 6 receipts. It writes -19
only and reads -8 only under an Ed25519 statement key. Measured on 2026-10-08
with these pinned versions: pycose 1.1.0 (with cbor2 5.9.0) and go-cose v1.3.0
verified the statement with alg -8, refused the same statement with one
signature bit changed, and reported alg -19 (vector M2) as an unknown
algorithm; microsoft/scitt-verifier 0.4.0 evaluated the signature of neither
statement (its result for both was cannot-evaluate, with the statement
signature not evaluated).¶
The signature of M2 (alg -19) is checked from the text alone, without a COSE library: a script written from the texts of this document and of [RECEIPTS] builds the Sig_structure by hand and verifies the signature over it with a general Ed25519 implementation (its checks M2-17 and M2-18).¶
The values below are derived from vectors of [RECEIPTS] (P1, and the candidates named in Table 1) and from the issuer test key of that document, whose seed is given there; the issuer URI of the Signed Statement is a constant of this example. PURE TEST KEY. It MUST NOT be used for anything real.¶
Type:¶
application/vnd.signed-evidence.eval-receipt+json¶
Issuer test key, public key (base64 and hex):¶
x7ppA99DtumHO/Au0M/gumSK8IwCzNwPiID92BSFbak= c7ba6903df43b6e9873bf02ed0cfe0ba648af08c02ccdc0f8880fdd814856da9¶
Issuer URI of the Signed Statement (iss):¶
https://issuer.example/eval¶
B, 458 bytes (hex):¶
7b22636f6d6d69745f616c67223a227368613235362d73616c7465642d763122 2c22636f6d70617261746f72223a223e3d222c22646174617365745f69645f63 6f6d6d6974223a227368613235363a6132316261346439366338303364343236 3364643364323136316263303339613330663434363262643539343730653331 626135613961623061396233623633222c226d6574726963223a226163637572 616379222c226d6f64656c5f69645f636f6d6d6974223a227368613235363a39 3034646534323536326639613139363531653139656237616231363565346666 6531313463653561326639386535376461353833383935393638346662306622 2c226e223a313830302c22706173736564223a747275652c22736368656d6122 3a2268747470733a2f2f7369676e65642d65766964656e63652e6f72672f6576 616c2d726563656970742f7631222c2273636f7265223a22302e383334222c22 7375697465223a2261636d652d7361666574792d7375697465222c2273756974 655f76657273696f6e223a22312e322e30222c227468726573686f6c64223a22 302e383030222c2274696d657374616d70223a22323032362d31302d30325430 303a30303a30305a227d¶
Receipt digest, SHA-256 over B:¶
8cd849a6dcce08aee334511d7b2f31c54e478885dda1795d3c8f972dd0d4811c¶
SHA-256 over the receipt bytes of P1; not the receipt digest:¶
02036d1f57509858330383755ec16c532bdc58b0f2d949464488d57abc9f95e7¶
Every case cites B of P1. Cases C1 to C7 cite, with the algorithm sha-256, the receipt digest given in Appendix A.2. C8 cites, with the algorithm sha-512, this value over the same B:¶
d5cccf69bb4f9b2c6d102e1a4da3d057cf8fc00bbbae69c0889bb423d243e246 1685c907c22f86f34c15290063ee3cd0c5815a85e25e40ef1609fcd4e11c2dc8¶
The candidates are the vectors of [RECEIPTS] named in Table 1, whose bytes are given there. Case and SHA-256 over the candidate's receipt bytes:¶
C1 02036d1f57509858330383755ec16c532bdc58b0f2d949464488d57abc9f95e7 C2 c2a7943f0ea3de6e9da88c11925b1e112d32f697a403f07fcfbc3776bca10e72 C3 2c8144d50b4cc42a712d84e4d0417e52b0d8cbc484ad8e6d8d4b36a429b94ec1 C4 2405d1783d1803ddea207c027622fba40b3e82161686505ee96988e306e17278 C5 18b1b6dc631cf0f00d8b0d2c237b28a67b12c2d7088ae0313a2fb27760f96bdd C6 31a34194edd90bade6568a3cb00dbb983dabab9efccfd7a8b38650bd3e8d5201 C7 8966f27c5f2566d986b0ab7821060ea0c901504fe984d450dfc7f8ca7d1c27e1 C8 02036d1f57509858330383755ec16c532bdc58b0f2d949464488d57abc9f95e7¶
The expected results are those of Table 1; the reasons are:¶
C1: SHA-256 over the candidate's B equals the cited digest.¶
C2: SHA-256 over the candidate's B equals the cited digest.¶
C3: SHA-256 over the candidate's B equals the cited digest.¶
C4: SHA-256 over the candidate's B differs from the cited digest.¶
C5: SHA-256 over the candidate's B equals the cited digest.¶
C8: Citation algorithm not defined.¶
The envelope is a JSON object with the members payloadType, payload and signatures, serialized without insignificant whitespace and with members sorted by name. Its only signature is signature.sig of P1, unchanged; it verifies as Ed25519 over PAE(payloadType, payload) under the issuer test key.¶
PAE(type, B), 522 bytes (hex):¶
445353457631203439206170706c69636174696f6e2f766e642e7369676e6564 2d65766964656e63652e6576616c2d726563656970742b6a736f6e2034353820 7b22636f6d6d69745f616c67223a227368613235362d73616c7465642d763122 2c22636f6d70617261746f72223a223e3d222c22646174617365745f69645f63 6f6d6d6974223a227368613235363a6132316261346439366338303364343236 3364643364323136316263303339613330663434363262643539343730653331 626135613961623061396233623633222c226d6574726963223a226163637572 616379222c226d6f64656c5f69645f636f6d6d6974223a227368613235363a39 3034646534323536326639613139363531653139656237616231363565346666 6531313463653561326639386535376461353833383935393638346662306622 2c226e223a313830302c22706173736564223a747275652c22736368656d6122 3a2268747470733a2f2f7369676e65642d65766964656e63652e6f72672f6576 616c2d726563656970742f7631222c2273636f7265223a22302e383334222c22 7375697465223a2261636d652d7361666574792d7375697465222c2273756974 655f76657273696f6e223a22312e322e30222c227468726573686f6c64223a22 302e383030222c2274696d657374616d70223a22323032362d31302d30325430 303a30303a30305a227d¶
Envelope, 806 bytes (hex):¶
7b227061796c6f6164223a2265794a6a62323174615852665957786e496a6f69 633268684d6a55324c584e686248526c5a4331324d534973496d4e7662584268 636d4630623349694f69492b50534973496d52686447467a5a58526661575266 5932397462576c30496a6f69633268684d6a55324f6d45794d574a684e475135 4e6d4d344d444e6b4e4449324d32526b4d3251794d545978596d4d774d7a6c68 4d7a426d4e4451324d6d4a6b4e546b304e7a426c4d7a4669595456684f574669 4d474535596a4e694e6a4d694c434a745a58527961574d694f694a6859324e31 636d466a65534973496d31765a47567358326c6b58324e766257317064434936 496e4e6f595449314e6a6f354d44526b5a5451794e5459795a6a6c684d546b32 4e54466c4d546c6c596a6468596a45324e5755305a6d5a6c4d54453059325531 59544a6d4f54686c4e54646b595455344d7a67354e546b324f44526d596a426d 49697769626949364d5467774d4377696347467a6332566b496a7030636e566c 4c434a7a5932686c625745694f694a6f64485277637a6f764c334e705a32356c 5a43316c646d6c6b5a57356a5a533576636d63765a585a68624331795a574e6c 615842304c3359784969776963324e76636d55694f6949774c6a677a4e434973 496e4e316158526c496a6f6959574e745a53317a59575a6c64486b7463335670 644755694c434a7a64576c305a5639325a584a7a61573975496a6f694d533479 4c6a41694c434a3061484a6c63326876624751694f6949774c6a67774d434973 496e52706257567a6447467463434936496a49774d6a59744d5441744d444a55 4d4441364d4441364d444261496e303d222c227061796c6f616454797065223a 226170706c69636174696f6e2f766e642e7369676e65642d65766964656e6365 2e6576616c2d726563656970742b6a736f6e222c227369676e61747572657322 3a5b7b22736967223a22434247744e323639464f68505372357865307a6c4a47 53424e427a47696e457a38693031664d36312b4a4e614a50646e5a793148626f 596934656d686d384b5a715055337973546d726d434578537653786f637a4241 3d3d227d5d7d¶
SHA-256 over the envelope bytes; not the receipt digest:¶
d96e0b9635949045a6f7c7b29eac8c163f6fad0d6d0bff446beeff601e45fed0¶
A COSE_Sign1 with CBOR tag 18 in the form of a COSE Hash Envelope. The protected header holds these parameters, in this order:¶
1 (alg): -19¶
4 (kid): a 32-byte string, given below¶
15 (CWT Claims): a map with 1 (iss), the URI of Appendix A.1, and 2 (sub), the text string given below¶
258 (payload hash algorithm): -16¶
259 (preimage content type): the type, as a text string¶
kid, the COSE Key Thumbprint (SHA-256) of the issuer test key (hex):¶
c94d618c32417cedb44280d4d66029e6486aa834802d12cd919c817453eb1561¶
sub, the model commitment of B:¶
sha256:904de42562f9a19651e19eb7ab165e4ffe114ce5a2f98e57da5838959684fb0f¶
Protected header, 202 bytes (hex):¶
a50132045820c94d618c32417cedb44280d4d66029e6486aa834802d12cd919c 817453eb15610fa201781b68747470733a2f2f6973737565722e6578616d706c 652f6576616c0278477368613235363a39303464653432353632663961313936 3531653139656237616231363565346666653131346365356132663938653537 646135383338393539363834666230661901022f19010378316170706c696361 74696f6e2f766e642e7369676e65642d65766964656e63652e6576616c2d7265 63656970742b6a736f6e¶
The unprotected header is the empty map. The payload is the receipt digest given in Appendix A.2.¶
Sig_structure (ToBeSigned), 251 bytes (hex), with external_aad the empty byte string:¶
846a5369676e61747572653158caa50132045820c94d618c32417cedb44280d4 d66029e6486aa834802d12cd919c817453eb15610fa201781b68747470733a2f 2f6973737565722e6578616d706c652f6576616c0278477368613235363a3930 3464653432353632663961313936353165313965623761623136356534666665 3131346365356132663938653537646135383338393539363834666230661901 022f19010378316170706c69636174696f6e2f766e642e7369676e65642d6576 6964656e63652e6576616c2d726563656970742b6a736f6e4058208cd849a6dc ce08aee334511d7b2f31c54e478885dda1795d3c8f972dd0d4811c¶
Signature, Ed25519 over the Sig_structure (hex):¶
f8be22ab6b1c196611d884ea635f610ac45c042ab7958828c2af46dd5e35ac8d 66b0c01fc115f7d93597f3cf783e95df37ef78da9006b773e08e6239af01a10e¶
COSE_Sign1, 307 bytes (hex):¶
d28458caa50132045820c94d618c32417cedb44280d4d66029e6486aa834802d 12cd919c817453eb15610fa201781b68747470733a2f2f6973737565722e6578 616d706c652f6576616c0278477368613235363a393034646534323536326639 6131393635316531396562376162313635653466666531313463653561326639 38653537646135383338393539363834666230661901022f1901037831617070 6c69636174696f6e2f766e642e7369676e65642d65766964656e63652e657661 6c2d726563656970742b6a736f6ea058208cd849a6dcce08aee334511d7b2f31 c54e478885dda1795d3c8f972dd0d4811c5840f8be22ab6b1c196611d884ea63 5f610ac45c042ab7958828c2af46dd5e35ac8d66b0c01fc115f7d93597f3cf78 3e95df37ef78da9006b773e08e6239af01a10e¶
SHA-256 over the COSE_Sign1 bytes:¶
64e78be4636b8d1e90cb7a1ebe06c4cfba2848603d6f64958d7c2080a901c575¶
References. The in-toto references are pinned to release v1.2.0 of the in-toto Attestation Framework.¶
The draft names of [RECEIPTS] and [STATEMENT-ID] are to be updated once those documents are published.¶
The artifact-type declaration of Section 5.1 is named by no consuming profile yet.¶