SCITT: statements, receipts, transparency
An issuer signs a statement, a transparency service records it in an append-only log and hands back a receipt, and anyone holding the two public keys can check both offline.
1What it is
SCITT is an IETF architecture in which an issuer signs a statement and registers it with a transparency service that keeps an append-only log.
On registration the service returns a receipt, a signed proof that the statement sits at a given position in its log at a given size.
A verifier holding the issuer's public key and the log's public key can check the statement and the receipt from the bytes alone, without contacting either party.
2Design choices
iss, sub).iss/sub is not a Signed Statement and a registrar wraps the capsule ID in one. (RFC 9943; draft-mih-scitt-agent-action-capsule-05 §3.3)vds, label 395) and carries the proof in its header (label 396).fail-attached-payload)3What it shows / what it does not
Shows
- The issuer's key signed exactly these statement bytes (signature check).
- The statement's leaf is at
leaf_indexin the log attree_size, under a root the log key signed (inclusion). - The time of registration, but only if the receipt carries a signed time claim.
- Given two signed tree heads and a consistency proof, that the log only appended between them.
Does not show
- That the statement's content is true, or that the issuer was entitled to make it.
- That the log is complete: anything the issuer never registered is simply absent.
- That other parties see the same log; one receipt cannot rule out a different view shown elsewhere unless tree heads are compared through consistency checks.
- That the issuer's key belongs to who you think; key authorization is the verifier's own policy.
4Example
The expected values for a valid EdDSA signed statement and its RFC9162_SHA256 receipt, from the cross-implementation vector set. The Python and Go verifiers check both halves; the Rust verifier is receipt-only and checks only the receipt half.
{
"description": "Happy path: EdDSA Signed Statement + RFC9162_SHA256 receipt; everything verifies.",
"payload_sha256": "08b6e9ec3bd002da4e21976b6dc1411567d30acb30d671161583b3d8351e7692",
"protected_header": {
"statement": {
"alg": "EdDSA",
"alg_code": -8,
"content_type": "application/json",
"cwt_claims_label": 15,
"issuer": "https://test-vectors.scitt-cose.invalid",
"subject": "urn:scitt-cose:test-vectors:v1:valid-eddsa"
},
"receipt": {
"alg": "EdDSA",
"alg_code": -8,
"vds_label": 395,
"vds": 1
}
},
"leaf_entry": "a6dd4523ffdda1754c234acf209bdde758db7d30438468700a7bf6c01e800e3a",
"leaf_index": 2,
"tree_size": 8,
"inclusion_path": [
"d5790c062bb617c193f8dbedf90469ccf49525739238b6d1102df4d3424fbd44",
"fb85d1461099612b0a34168f8f207bc9a761a91cd1173f39c5dd7ca4d1d92a6c",
"b8e2ffb9ad6e45622e44393e6f58a747c4c5b3900d9676e3ecf50aab2ba266e4"
],
"reconstructed_root": "5c834b80c0b40ca993f0b4a3ef9d2e77a8a3e8113358e4f318866c02cd448362",
"statement_signature_valid": true,
"receipt_valid": true,
"result": "VALID"
}
| Field | Type | Meaning |
|---|---|---|
| payload_sha256 | hex | SHA-256 of the statement's payload bytes (opaque to the log). |
| protected_header.statement | map | Statement alg, content type, and CWT claims at label 15: issuer and subject. |
| protected_header.receipt | map | Receipt alg and vds at label 395; 1 is RFC9162_SHA256. |
| leaf_entry | hex | The log's leaf: in this vector set, SHA-256 of the complete statement bytes. |
| leaf_index, tree_size | uint | Position of the leaf and size of the log the receipt speaks for. |
| inclusion_path | hex[] | The audit path: sibling hashes from the leaf up to the root. |
| reconstructed_root | hex | The root a correct verifier recomputes; the receipt's detached payload. |
| statement_signature_valid | bool | Whether the statement signature must verify under the issuer key. |
| receipt_valid | bool | Whether the receipt must verify under the log key. |
| result | tstr | Overall verdict, VALID or INVALID. |
Source: action-state-group/scitt-cose:test-vectors/v1/valid-eddsa/expected.json @ ac9d3b90d058ff609497573a68402e561fa99404
5Specs
- RFC RFC 9943 — SCITT architecture: issuers, signed statements, transparency services, Registration Policy.
- RFC RFC 9942 — COSE Receipts: the
vdsand proof header parameters. - RFC RFC 9052 — COSE: the COSE_Sign1 structure used by both statement and receipt.
- Internet-Draft draft-mih-scitt-agent-action-capsule-05 — how a capsule ID is registered as a Signed Statement (§3.3).
- Internet-Draft draft-mih-scitt-checkpointed-local-log-02 — registering a local log's checkpoints instead of every entry (next page).
- Code action-state-group/scitt-cose — receipt verifier (Python, Go, Rust) and the vectors above.