Zero-knowledge circuits for software supply-chain compliance, written in Noir.
These circuits prove a software release satisfies a named compliance policy — build provenance, developer authorisation, SBOM hygiene, incident-notification SLA — without exposing the underlying SBOM, builder identities, customer list, or incident contents to the buyer. Each circuit reasons over signed evidence already produced upstream by Sigstore, GitHub Actions, OSV.dev, or the vendor’s mail provider.
For the full motivation, regulatory mapping, and per-circuit threat model, see the Colofon whitepaper and per-circuit deep-dives.
A Colofon bundle is the composition of up to five inner proofs. Circuits 1–4 each produce an independently-verifiable proof; Circuit 5 wraps them in a single recursive proof that the buyer’s browser verifies in one shot.
┌──────────────────────┐
SLSA ─────▶│ 01 Build provenance │──── binary digest came from approved pipeline
└──────────┬───────────┘
│
┌──────────▼───────────┐
gitsign ───▶│ 02 Developer auth │──── commit signed by authorised set member
└──────────┬───────────┘
│
┌──────────▼───────────┐
SBOM ───▶│ 03 SBOM non-membership│──── no component carries unpatched CVE > threshold
OSV ───▶│ (headline) │
└──────────┬───────────┘
│
┌──────────▼───────────┐
DKIM ───▶│ 04 Notification SLA │──── customer notified within window of incident
└──────────┬───────────┘
│
┌──────────▼───────────┐
│ 05 Policy composition │──── all four verify against buyer-committed policy
│ (recursive wrapper) │ (one proving run, any number of buyer policies)
└───────────────────────┘
| # | Crate | What it proves | Public inputs |
|---|---|---|---|
| 01 | build_provenance |
Binary digest produced by an authorised build pipeline (SLSA v1.0 in-toto provenance, Fulcio-keyless-signed via GitHub Actions OIDC, Rekor-anchored). Signing identity is in the buyer’s approved-builder Merkle set. | pae_digest_hash, approved_builder_root, signer_commitment, binary_digest_high/low |
| 02 | dev_auth |
Commit triggering the build was gitsign-signed by an authorised developer, without revealing which one. | commit_hash_high/low, authorised_signer_root, signer_commitment |
| 03 | sbom_non_membership |
No component in the committed CycloneDX SBOM is present in the buyer’s policy-filtered CVE Indexed Merkle Tree. SBOM root is bound to Circuit 1’s SLSA subject. | sbom_root, cve_tree_root, component_count |
| 04 | dkim_sla |
A DKIM-RSA-2048-signed notification email was sent to an approved recipient, naming a specific incident, with a mail-provider-attested timestamp and a sender-domain double-binding (From-domain ≡ DKIM d=). |
dkim_pubkey_hash, signed_digest_commitment, sender_domain_hash, send_timestamp_unix, recipient_identity_hash, approved_recipient_root, incident_id_hash |
| 05 | policy_composition |
All inner proofs verify against the buyer-committed policy. v1a wraps a single Circuit 4 proof; v1b/v1c expand to multi-inner aggregation across 1–4. | Pass-through of inner public inputs (v1a); collapsed to bundle-level commitments (v1c) |
| Crate | Purpose |
|---|---|
imt (colofon_imt) |
Indexed Merkle Tree primitives for non-membership proofs. Ported from AztecProtocol/aztec-packages and generalised for standalone use; depended on by Circuits 1–4. |
imt_bench |
Reference-sized IMT (CVE_TREE_HEIGHT = 32) for proving-time benchmarking. |
- Nargo v1.0.0-beta.19 — circuits depend on beta.19-specific features. Install:
noirup -v 1.0.0-beta.19
- @aztec/bb.js 4.1.3 for proving and verification.
# Single circuit
cd build_provenance
nargo compile
# All workspace members
nargo compile --workspacecd imt
nargo test
# Or run the whole workspace's tests
nargo test --workspacepolicy_composition proves recursively under UltraHonk-with-ZK and requires the outer Barretenberg instance to initialise the Grumpkin SRS to 221 points. This is automatic in colofon-prover and any host that calls Barretenberg.initSRSChonk(2**21) before the first proof; see colofon-prover/Dockerfile for the production-image setup that pre-downloads and pins the CRS.
| Library | Version | Used by | Purpose |
|---|---|---|---|
sha256 |
0.3.0 | 01, 04 | SHA-256 hash computation in-circuit |
poseidon |
0.1.1 | 01, 02, 03, 04, IMT | ZK-friendly Poseidon2 hash for commitments and Merkle trees |
noir_rsa (zkpassport fork) |
0.10.0 | 04 | RSA-2048 PKCS#1v1.5 verification for DKIM signatures |
bignum |
0.9.2 | 04 | Big-integer arithmetic for RSA limbs |
base64 |
0.4.2 | 04 | Base64 decoding for DKIM bh= body-hash tag |
bb_proof_verification |
v4.0.0-devnet.2-patch.3 | 05 | Recursive UltraHonk proof verification |
colofon_imt |
local | 01, 02, 03, 04 | In-tree IMT membership and non-membership primitives |
The DKIM stack uses zkpassport’s noir_rsa fork, the same RSA-2048 stack Apertrue’s C2PA circuits run in production. (We evaluated zkemail.nr v2.0.0 in the Gate-0 OSS scan but it required idents and integer-arithmetic patterns that beta.19 has tightened, so it didn’t compile against our pinned Noir version. Tracked for re-evaluation when zkemail.nr publishes a Noir-1.0-compatible release.)
- Signed-input grounding. Every circuit takes as witness an artefact signed by a third party that is not the vendor (Sigstore-keyless GitHub Actions, gitsign commit signatures, OSV.dev CVE feed, mail-provider DKIM). Vendor self-attestation alone never satisfies a circuit.
- Trust boundary. X.509 / Fulcio chain validation and Rekor inclusion proofs are performed off-circuit by
colofon-sdkbefore witness construction. The circuits trust the SDK to derivebuilder_identity_hash/signer_identity_hashfrom the validated SAN URI; an SDK-level bug here would be a soundness bug at the bundle level even when the circuit itself is sound. Independent cryptographic review of the SDK’s SAN parser is part of the pre-launch audit scope. - Cross-circuit binding. Circuits 1–4 commit to overlapping anchors (the binary digest, the commit hash, the SBOM root, the incident ID, the customer-set root). The bundle verifier — and, in v1c, Circuit 5 itself — cross-checks these so a bundle assembled from inconsistent inner proofs is rejected.
- Pubkey-to-identity binding. Circuits 1 and 2 each emit a
signer_commitment = Poseidon2(pubkey_halves, identity_hash). Without this, a prover could mix one identity’s key with another’s Merkle opening and the proof would still verify; the binding closes that gap. - Sender-domain double-binding (Circuit 4). The From-header domain and the DKIM-Signature
d=tag value both hash to the same publicsender_domain_hash. Closes the shared-key / mail-relay attack where an adversary holding a DKIM signature for one domain substitutes a different domain in the From: header. - Honest caveats. Each deep-dive page documents the circuit’s limitations explicitly — the SLSA subject-digest anchor is substring-based rather than structural; the OSV trust anchor is HTTPS-pinned in v1, Sigstore-signed in v2; Circuit 4’s anchor-based header parsing leans on Merkle membership for its real soundness rather than the byte anchors alone. See the per-circuit deep-dives.
- No independent cryptographic audit yet. One is in progress; the whitepaper is the current authoritative reference.
These circuits are built on the work of:
- Noir by Aztec Labs — zero-knowledge circuit language and compiler
- Barretenberg by Aztec Labs — UltraHonk proving backend and recursive verification
- Aztec Indexed Merkle Tree by Aztec Labs — non-membership-friendly tree construction;
colofon_imtis a port-and-generalise of the protocol-internal version into a standalone Noir library noir_rsaby zkpassport — RSA verification used for DKIM signature checks in Circuit 4noir-bignum,poseidon,sha256,noir_base64by Noir Lang — standard cryptographic primitives- Sigstore (Linux Foundation / OpenSSF) — keyless signing, Rekor transparency log, gitsign, Fulcio
- SLSA by OpenSSF — in-toto attestation framework that Circuit 1 proves over
- CycloneDX by OWASP — SBOM specification consumed by Circuit 3
- OSV.dev by Google — CVE feed used as the trust anchor for Circuit 3’s policy-filtered exclusion tree
- The ZK Email project — reference work on in-circuit DKIM verification that informed Circuit 4’s design
Apertrue Ltd’s C2PA media-authenticity stack (production since 2025) provided the Noir / Barretenberg / Aztec proving infrastructure pattern, the recursive aggregation primitive, and several cryptographic primitives that Colofon reuses directly.
Apache 2.0 — Copyright 2026 Apertrue Ltd / Colofon. See LICENSE.