Privacy testing
Privacy is tested at the scenario-framework level: the guarantee under test is that the scenario layer never exposes confidential values on its own public surfaces — observations, logs, serialized results, reports, or failure diagnostics. Nothing here tests the cryptography of the underlying Confidential Token implementation; it tests the surfaces this repository controls.
Threat model
The leaks this suite defends against are accidental, not cryptographic:
- a working pipeline that serializes its inputs into a report;
- an error path that echoes the rejected payload back in its diagnostic;
- a proof step that copies witness material into public inputs;
- a log line that prints an operation or observation with
{:?}.
Failure paths are treated as more dangerous than success paths, because error handling is where payloads get echoed.
Layered enforcement
No single mechanism carries the guarantee; each layer independently catches a different failure:
- Type-level classification (
scenario-core::observation) — every observation carries aVisibility. Non-public values serialize as[REDACTED], andDebugnever renders them. A leak would require deliberately authoring a public observation with a private value. - Definition-time guard (
scenario-core::scenario) — aGenerateProofstep whose public inputs name a confidential field (amount, witness, secret, nonce, opening, randomness, confidential) fails to build. Confidential values never belong in public inputs. - Runner expectations —
ExpectationKind::NotDisclosedpins specific keys (e.g.op.op-transfer.amount) that must never become observations. - Privacy invariant (
invariants, keyprivacy) — scans every public observation key for confidential markers; a public observation whose key names a confidential concept would leak structure even with a redacted value. - Report hygiene (pack tests) — whole
ScenarioOutcomes are serialized to JSON and the confidential literals are asserted absent on both success and failure paths.
Scenarios
The privacy pack (CT-PRIV-001..004) exercises both paths:
| Id | Path | What it pins |
|---|---|---|
| CT-PRIV-001 | success | a confidential transfer completes while the 30-unit amount and witness material never become public observations |
| CT-PRIV-002 | failure | a rejected transfer discloses only its classification code, never the attempted 9000-unit amount |
| CT-PRIV-003 | proof | the proof statement binds only public protocol values; generation and verification observations never name amount/witness |
| CT-PRIV-004 | failure | a tampered proof fails verification without leaking witness material |
Run them with:
cargo run -p cli --bin crucible-scenarios -- run --category privacy
cargo run -p cli --bin crucible-scenarios -- report
What is and is not guaranteed
- Guaranteed: no confidential amount or witness value enters an observation, a serialized outcome, or a failure diagnostic of this framework; no proof-generation step can declare confidential public inputs; fixtures contain no secret-carrying fields.
- Not guaranteed: cryptographic privacy of the underlying protocol —
that belongs to the Confidential Token implementation and the real
prover. Re-validate against the real
crucible-simulator/crucible-proverbefore making external privacy claims.