Skip to content

Experimental RFC9162_SHA256 receipt support for IETF 126 - #424

Open
Amaury Chamayou (achamayou) wants to merge 9 commits into
microsoft:mainfrom
achamayou:achamayou-support-rfc9942-receipts
Open

Experimental RFC9162_SHA256 receipt support for IETF 126#424
Amaury Chamayou (achamayou) wants to merge 9 commits into
microsoft:mainfrom
achamayou:achamayou-support-rfc9942-receipts

Conversation

@achamayou

Copy link
Copy Markdown
Member

Context

This is an experimental addition for interoperability work at the IETF 126 Hackathon. It adds early pyscitt support for RFC 9942 receipts using the RFC9162_SHA256 profile (vds=1). It is intentionally scoped to the published examples rather than presented as complete RFC 9942 profile coverage.

The existing CCF receipt path remains separate and is dispatched only for vds=2.

What changed

  • Reconstruct RFC 9162 SHA-256 Merkle roots from RFC 9942 inclusion proofs and verify detached COSE signatures with pycose.
  • Dispatch receipts from the protected vds header: RFC9162_SHA256 for vds=1, CCF for vds=2, and reject missing, malformed, or unknown values.
  • Keep validation centered on Transparent Statements while allowing an explicit --service-key as an alternative to a service trust store.
  • Pin the IETF SCITT valid-es256 and fail-tampered-path vectors at commit 727ee03d86fa2c2ca8c534584b870235a1b252df.
  • Add derived Transparent Statements that embed each published receipt under header label 394 and strip byte-for-byte to the original signed statements.
  • Verify the valid example and reject the published tampered inclusion path with a clear proof/signature error.

Experimental notes

  • The published examples do not carry a kid, so validation uses an explicitly trusted log key.
  • The source vectors provide receipts separately; the checked-in Transparent Statements are derived test inputs for pyscitt's unified validation route.

Validation

  • pytest test/test_rfc9942.py test/test_verify.py -q — 28 passed
  • CI-equivalent mypy, isort, Black, C/C++ formatting, notice, and changelog checks passed locally
  • The complete CCF-backed functional suite is left to the configured upstream CI runner

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8a32fc93-3458-41a3-b2e1-a51273957e02
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8a32fc93-3458-41a3-b2e1-a51273957e02
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds experimental pyscitt verification support for RFC 9942 Transparent Statements carrying RFC9162_SHA256 receipts (vds=1), while keeping the existing CCF receipt verification path for vds=2.

Changes:

  • Implement RFC 9162 SHA-256 Merkle root reconstruction from RFC 9942 inclusion proofs and verify detached COSE signatures via pycose.
  • Dispatch receipt verification based on protected header vds (accept 1 and 2; reject missing/malformed/unknown).
  • Add CLI support for explicitly trusting a PEM service public key (--service-key) and add pinned IETF example vectors + tests.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
pyscitt/pyscitt/verify.py Adds vds-based dispatch and RFC9162_SHA256 receipt verification implementation.
pyscitt/pyscitt/cli/validate.py Adds --service-key trust option and wiring into transparent statement validation.
pyscitt/README.md Documents validating RFC 9942 Transparent Statements with --service-key.
test/test_rfc9942.py Adds tests covering pinned vectors, transparent statement stripping, dispatch, and tampered-path rejection.
test/test_verify.py Updates transparent statement verification tests to set vds=2 on synthetic CCF receipts.
.gitattributes Marks .cose vectors as binary and disables text normalization for .pub keys.
test/test_vectors/scitt-cose/v1/valid-es256/transparent-statement.cose Adds pinned “valid-es256” transparent statement test vector.
test/test_vectors/scitt-cose/v1/valid-es256/statement.cose Adds pinned “valid-es256” statement test vector.
test/test_vectors/scitt-cose/v1/valid-es256/receipt.cose Adds pinned “valid-es256” receipt test vector.
test/test_vectors/scitt-cose/v1/valid-es256/log-key.pub Adds pinned “valid-es256” log public key.
test/test_vectors/scitt-cose/v1/fail-tampered-path/transparent-statement.cose Adds pinned “fail-tampered-path” transparent statement test vector.
test/test_vectors/scitt-cose/v1/fail-tampered-path/statement.cose Adds pinned “fail-tampered-path” statement test vector.
test/test_vectors/scitt-cose/v1/fail-tampered-path/receipt.cose Adds pinned “fail-tampered-path” receipt test vector.
test/test_vectors/scitt-cose/v1/fail-tampered-path/log-key.pub Adds pinned “fail-tampered-path” log public key.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pyscitt/pyscitt/verify.py Outdated
Comment thread test/test_verify.py
Comment thread test/test_verify.py
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8a32fc93-3458-41a3-b2e1-a51273957e02
def validate_transparent_statement(
statement: Path,
service_trust_store_path: Optional[Path] = None,
service_key: Optional[Path] = None,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is allowing a service key to be passed directly, instead of a path to a trust store containing certificates. That's necessary to support baseline COSE Receipts with RFC9162_SHA256 proofs and no x509 integration.

Comment thread pyscitt/pyscitt/verify.py

if type(vds) is not int:
raise ValueError(f"unsupported receipt vds: {vds}")

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main change is to dispatch on VDS type here. The CCF branch is unchanged of course.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8a32fc93-3458-41a3-b2e1-a51273957e02
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8a32fc93-3458-41a3-b2e1-a51273957e02
@achamayou
Amaury Chamayou (achamayou) marked this pull request as ready for review July 20, 2026 14:52
@achamayou
Amaury Chamayou (achamayou) requested a review from a team as a code owner July 20, 2026 14:52
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants