# Sigstore Bundle Format This document describes the Sigstore Bundle v0.3 format implementation in StellaOps for offline DSSE envelope verification. ## Overview A Sigstore bundle is a self-contained package that includes all verification material needed to verify a DSSE envelope without network access. This enables offline verification scenarios critical for air-gapped environments. ## Bundle Structure ```json { "mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial": { "certificate": { ... }, "tlogEntries": [ ... ], "timestampVerificationData": { ... } }, "dsseEnvelope": { "payloadType": "application/vnd.in-toto+json", "payload": "", "signatures": [ { "sig": "", "keyid": "" } ] } } ``` ## Components ### Media Type - **v0.3**: `application/vnd.dev.sigstore.bundle.v0.3+json` (current) - **v0.2**: `application/vnd.dev.sigstore.bundle.v0.2+json` (legacy) ### Verification Material Contains cryptographic material for verification: | Field | Type | Description | |-------|------|-------------| | `certificate` | Object | X.509 signing certificate (keyless signing) | | `publicKey` | Object | Public key (keyful signing, alternative to certificate) | | `tlogEntries` | Array | Transparency log entries from Rekor | | `timestampVerificationData` | Object | RFC 3161 timestamps | #### Certificate ```json { "certificate": { "rawBytes": "" } } ``` #### Public Key (alternative to certificate) ```json { "publicKey": { "hint": "", "rawBytes": "" } } ``` ### Transparency Log Entry ```json { "logIndex": "12345", "logId": { "keyId": "" }, "kindVersion": { "kind": "dsse", "version": "0.0.1" }, "integratedTime": "1703500000", "inclusionPromise": { "signedEntryTimestamp": "" }, "inclusionProof": { "logIndex": "12345", "rootHash": "", "treeSize": "100000", "hashes": ["", ...], "checkpoint": { "envelope": "" } }, "canonicalizedBody": "" } ``` ### DSSE Envelope Standard DSSE envelope format: ```json { "payloadType": "application/vnd.in-toto+json", "payload": "", "signatures": [ { "sig": "", "keyid": "" } ] } ``` ## Usage ### Building a Bundle ```csharp using StellaOps.Attestor.Bundle.Builder; using StellaOps.Attestor.Bundle.Models; var bundle = new SigstoreBundleBuilder() .WithDsseEnvelope(payloadType, payload, signatures) .WithCertificate(certificateBytes) .WithRekorEntry( logIndex: "12345", logIdKeyId: logKeyId, integratedTime: "1703500000", canonicalizedBody: body) .WithInclusionProof(inclusionProof) .Build(); // Serialize to JSON var json = bundle.BuildJson(); File.WriteAllText("attestation.bundle", json); ``` ### Deserializing a Bundle ```csharp using StellaOps.Attestor.Bundle.Serialization; var json = File.ReadAllText("attestation.bundle"); var bundle = SigstoreBundleSerializer.Deserialize(json); // Or with error handling if (SigstoreBundleSerializer.TryDeserialize(json, out var bundle)) { // Use bundle } ``` ### Verifying a Bundle ```csharp using StellaOps.Attestor.Bundle.Verification; var verifier = new SigstoreBundleVerifier(); var result = await verifier.VerifyAsync(bundle); if (result.IsValid) { Console.WriteLine("Bundle verified successfully"); Console.WriteLine($"DSSE Signature: {result.Checks.DsseSignature}"); Console.WriteLine($"Certificate Chain: {result.Checks.CertificateChain}"); Console.WriteLine($"Inclusion Proof: {result.Checks.InclusionProof}"); } else { foreach (var error in result.Errors) { Console.WriteLine($"Error: {error.Code} - {error.Message}"); } } ``` ### Verification Options ```csharp var options = new BundleVerificationOptions { VerifyInclusionProof = true, VerifyTimestamps = false, VerificationTime = DateTimeOffset.UtcNow, TrustedRoots = trustedCertificates }; var result = await verifier.VerifyAsync(bundle, options); ``` ## Verification Checks | Check | Description | |-------|-------------| | `DsseSignature` | Verifies DSSE signature using PAE encoding | | `CertificateChain` | Validates certificate validity period | | `InclusionProof` | Verifies Merkle inclusion proof (RFC 6962) | | `TransparencyLog` | Validates transparency log entry | | `Timestamp` | Verifies RFC 3161 timestamps (optional) | ## Error Codes | Code | Description | |------|-------------| | `InvalidBundleStructure` | Bundle JSON structure is invalid | | `MissingDsseEnvelope` | DSSE envelope is required | | `DsseSignatureInvalid` | Signature verification failed | | `MissingCertificate` | No certificate or public key | | `CertificateChainInvalid` | Certificate chain validation failed | | `CertificateExpired` | Certificate has expired | | `CertificateNotYetValid` | Certificate not yet valid | | `InclusionProofInvalid` | Merkle proof verification failed | | `RootHashMismatch` | Computed root doesn't match expected | ## Cosign Compatibility Bundles created by StellaOps are compatible with cosign verification: ```bash # Verify bundle with cosign cosign verify-attestation \ --bundle attestation.bundle \ --certificate-identity="subject@example.com" \ --certificate-oidc-issuer="https://issuer.example.com" \ --type=slsaprovenance \ registry.example.com/image:tag ``` See [Cosign Verification Examples](./cosign-verification-examples.md) for more details. ## References - [Sigstore Bundle Specification](https://github.com/sigstore/cosign/blob/main/specs/BUNDLE_SPEC.md) - [Sigstore Protobuf Specs](https://github.com/sigstore/protobuf-specs) - [DSSE Specification](https://github.com/secure-systems-lab/dsse) - [RFC 6962 - Certificate Transparency](https://www.rfc-editor.org/rfc/rfc6962)