Files
git.stella-ops.org/docs/modules/attestor/proof-chain-specification.md
StellaOps Bot b058dbe031 up
2025-12-14 23:20:14 +02:00

16 KiB

Proof and Evidence Chain Technical Specification

Version: 1.0 Status: Implementation Ready Source: docs/product-advisories/14-Dec-2025 - Proof and Evidence Chain Technical Reference.md Last Updated: 2025-12-14


Executive Summary

This specification defines the implementation of a cryptographically verifiable proof chain that links SBOM components to VEX verdicts through signed evidence and reasoning statements. The system provides complete traceability from scan results to policy decisions with deterministic, auditable outputs.

Architecture Overview

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                              PROOF CHAIN ARCHITECTURE                                │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                     │
│  ┌─────────────┐   ┌─────────────┐   ┌─────────────┐   ┌─────────────┐             │
│  │   Scanner   │──►│   Evidence  │──►│  Reasoning  │──►│     VEX     │             │
│  │    SBOM     │   │  Statements │   │  Statements │   │   Verdicts  │             │
│  │ (CycloneDX) │   │             │   │             │   │             │             │
│  └─────────────┘   └─────────────┘   └─────────────┘   └─────────────┘             │
│         │                │                │                │                        │
│         │                │                │                │                        │
│         ▼                ▼                ▼                ▼                        │
│  ┌─────────────────────────────────────────────────────────────────────────────┐   │
│  │                          CONTENT-ADDRESSED IDs                               │   │
│  │  SBOMEntryID | EvidenceID | ReasoningID | VEXVerdictID | ProofBundleID      │   │
│  └─────────────────────────────────────────────────────────────────────────────┘   │
│                                        │                                            │
│                                        ▼                                            │
│  ┌─────────────────────────────────────────────────────────────────────────────┐   │
│  │                              PROOF SPINE                                     │   │
│  │  Merkle aggregation: merkle_root(SBOMEntryID, EvidenceID[], ReasoningID,    │   │
│  │                                  VEXVerdictID) = ProofBundleID              │   │
│  └─────────────────────────────────────────────────────────────────────────────┘   │
│                                        │                                            │
│                                        ▼                                            │
│  ┌─────────────────────────────────────────────────────────────────────────────┐   │
│  │                           DSSE ENVELOPES                                     │   │
│  │  - In-toto Statement/v1 format                                              │   │
│  │  - Signed by role-specific keys                                              │   │
│  │  - Predicate types: evidence.stella/v1, reasoning.stella/v1,                │   │
│  │                     cdx-vex.stella/v1, proofspine.stella/v1                 │   │
│  └─────────────────────────────────────────────────────────────────────────────┘   │
│                                        │                                            │
│                                        ▼                                            │
│  ┌─────────────────────────────────────────────────────────────────────────────┐   │
│  │                         TRUST ANCHORS                                        │   │
│  │  - Per-dependency anchor (PURL pattern matching)                            │   │
│  │  - Allowed key IDs for verification                                          │   │
│  │  - Key rotation with historical validity                                     │   │
│  └─────────────────────────────────────────────────────────────────────────────┘   │
│                                        │                                            │
│                                        ▼                                            │
│  ┌─────────────────────────────────────────────────────────────────────────────┐   │
│  │                      REKOR TRANSPARENCY LOG                                  │   │
│  │  - Inclusion proofs for all DSSE envelopes                                  │   │
│  │  - Checkpoint verification                                                   │   │
│  │  - Offline verification support                                              │   │
│  └─────────────────────────────────────────────────────────────────────────────┘   │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘

Content-Addressed Identifier System

ID Formats

ID Type Format Example
ArtifactID sha256:<64-hex> sha256:a1b2c3d4e5f6...
SBOMEntryID <sbomDigest>:<purl>[@<version>] sha256:91f2ab3c:pkg:npm/lodash@4.17.21
EvidenceID sha256:<hash(canonical_json)> sha256:7b8c9d0e...
ReasoningID sha256:<hash(canonical_json)> sha256:4a5b6c7d...
VEXVerdictID sha256:<hash(canonical_json)> sha256:1f2e3d4c...
ProofBundleID sha256:<merkle_root> sha256:9e8d7c6b...
GraphRevisionID grv_sha256:<hash> grv_sha256:5a4b3c2d...
TrustAnchorID UUID v4 550e8400-e29b-41d4-a716-446655440000

Canonicalization Rules

  1. UTF-8 encoding for all strings
  2. Sorted keys (lexicographic, case-sensitive)
  3. No insignificant whitespace
  4. No trailing commas
  5. Numbers in shortest form
  6. Deterministic array ordering (by semantic key: bom-ref, purl)

DSSE Predicate Types

1. Evidence Statement (evidence.stella/v1)

{
  "predicateType": "evidence.stella/v1",
  "predicate": {
    "source": "scanner/feed name",
    "sourceVersion": "tool version",
    "collectionTime": "2025-12-14T00:00:00Z",
    "sbomEntryId": "<SBOMEntryID>",
    "vulnerabilityId": "CVE-XXXX-YYYY",
    "rawFinding": "<pointer or data>",
    "evidenceId": "<EvidenceID>"
  }
}

Signer: Scanner/Ingestor key

2. Reasoning Statement (reasoning.stella/v1)

{
  "predicateType": "reasoning.stella/v1",
  "predicate": {
    "sbomEntryId": "<SBOMEntryID>",
    "evidenceIds": ["<EvidenceID>", ...],
    "policyVersion": "v2.3.1",
    "inputs": {
      "currentEvaluationTime": "2025-12-14T00:00:00Z",
      "severityThresholds": {...},
      "latticeRules": {...}
    },
    "intermediateFindings": {...},
    "reasoningId": "<ReasoningID>"
  }
}

Signer: Policy/Authority key

3. VEX Verdict Statement (cdx-vex.stella/v1)

{
  "predicateType": "cdx-vex.stella/v1",
  "predicate": {
    "sbomEntryId": "<SBOMEntryID>",
    "vulnerabilityId": "CVE-XXXX-YYYY",
    "status": "not_affected|affected|fixed|under_investigation",
    "justification": "vulnerable_code_not_in_execute_path",
    "policyVersion": "v2.3.1",
    "reasoningId": "<ReasoningID>",
    "vexVerdictId": "<VEXVerdictID>"
  }
}

Signer: VEXer/Vendor key

4. Proof Spine Statement (proofspine.stella/v1)

{
  "predicateType": "proofspine.stella/v1",
  "predicate": {
    "sbomEntryId": "<SBOMEntryID>",
    "evidenceIds": ["<ID1>", "<ID2>"],
    "reasoningId": "<ID>",
    "vexVerdictId": "<ID>",
    "policyVersion": "v2.3.1",
    "proofBundleId": "<ProofBundleID>"
  }
}

Signer: Authority key

5. Verdict Receipt Statement (verdict.stella/v1)

{
  "predicateType": "verdict.stella/v1",
  "predicate": {
    "graphRevisionId": "<GraphRevisionID>",
    "findingKey": {"sbomEntryId": "<ID>", "vulnerabilityId": "CVE-..."},
    "rule": {"id": "POLICY-RULE-123", "version": "v2.3.1"},
    "decision": {"status": "block|warn|pass", "reason": "..."},
    "inputs": {"sbomDigest": "sha256:...", "feedsDigest": "sha256:...", "policyDigest": "sha256:..."},
    "outputs": {"proofBundleId": "<ID>", "reasoningId": "<ID>", "vexVerdictId": "<ID>"},
    "createdAt": "2025-12-14T00:00:00Z"
  }
}

Signer: Authority key

6. SBOM Linkage Statement (sbom-linkage/v1)

{
  "predicateType": "https://stella-ops.org/predicates/sbom-linkage/v1",
  "predicate": {
    "sbom": {"id": "<sbomId>", "format": "CycloneDX", "specVersion": "1.6", ...},
    "generator": {"name": "StellaOps.Sbomer", "version": "x.y.z"},
    "generatedAt": "2025-12-14T00:00:00Z",
    "incompleteSubjects": [],
    "tags": {"tenantId": "...", "projectId": "...", "pipelineRunId": "..."}
  }
}

Signer: Generator key

Database Schema

Tables

Table Purpose
proofchain.sbom_entries SBOM component entries with content-addressed IDs
proofchain.dsse_envelopes Signed DSSE envelopes by predicate type
proofchain.spines Proof spine aggregations linking evidence to verdicts
proofchain.trust_anchors Trust anchor configurations for verification
proofchain.rekor_entries Rekor transparency log entries
proofchain.key_history Key lifecycle history for rotation
proofchain.key_audit_log Audit log for key operations

API Endpoints

Endpoint Method Purpose
/proofs/{entry}/spine POST Create proof spine
/proofs/{entry}/receipt GET Get verification receipt
/proofs/{entry}/vex GET Get VEX document
/anchors/{anchor} GET/PUT Trust anchor management
/anchors/{anchor}/keys GET/POST Key management
/anchors/{anchor}/keys/{keyid}/revoke POST Key revocation
/verify POST Artifact verification
/keys/rotation-warnings GET Rotation warnings

CLI Exit Codes

Code Meaning
0 Success - no policy violations
1 Policy violation detected
2 System/scanner error

Verification Pipeline

The 13-step verification algorithm:

  1. Resolve SBOMEntryID → TrustAnchorID
  2. Fetch spine and trust anchor
  3. Verify spine DSSE signature against TrustAnchor.allowedKeyids
  4. Verify VEX DSSE signature
  5. Verify reasoning DSSE signature
  6. Verify evidence DSSE signatures
  7. Recompute EvidenceIDs from stored canonical evidence
  8. Recompute ReasoningID from reasoning
  9. Recompute VEXVerdictID from VEX body
  10. Recompute ProofBundleID (merkle root) from above
  11. Compare all computed IDs to stored IDs
  12. If using Rekor: verify log inclusion proof
  13. Emit Receipt

Key Rotation

Process

  1. Add new key to TrustAnchor.allowedKeyids
  2. Transition period: both keys valid
  3. Optionally revoke old key (moves to revokedKeys)
  4. Publish key material via attestation feed

Invariants

  • Never mutate old DSSE envelopes
  • Revoked keys remain valid for proofs signed before revocation
  • All key changes are audited

Implementation Sprints

Sprint Focus Status
0501.2 Content-Addressed IDs & Core Records TODO
0501.3 New DSSE Predicate Types TODO
0501.4 Proof Spine Assembly TODO
0501.5 API Surface & Verification Pipeline TODO
0501.6 Database Schema Implementation TODO
0501.7 CLI Integration & Exit Codes TODO
0501.8 Key Rotation & Trust Anchors TODO

Cryptographic Profiles

Profile Algorithm Use Case
default SHA256-ED25519 General purpose
fips SHA256-ECDSA-P256 FIPS 140-2/3 compliance
gost GOST R 34.10-2012 Russian regulatory
sm SM2/SM3 Chinese standards
pqc SHA256-DILITHIUM3 Post-quantum

Determinism Constraints

Non-Negotiable Invariants

  1. Immutability: DSSE envelopes are append-only
  2. Determinism: Same inputs → same outputs
  3. Traceability: Every verdict traceable to evidence
  4. Least Trust: Explicit trust via TrustAnchors only
  5. Backward Compatibility: New code verifies old proofs

Temporal Handling

  • UTC ISO-8601 only
  • No local time
  • Timestamps only when semantically required
  • Derivation from content preferred over wall-clock time

Document Version: 1.0 Target Platform: .NET 10, PostgreSQL ≥16, Angular v17