docs consolidation

This commit is contained in:
StellaOps Bot
2025-12-25 12:16:13 +02:00
parent deb82b4f03
commit 223843f1d1
34 changed files with 2141 additions and 106 deletions

View File

@@ -0,0 +1,239 @@
# 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": "<base64-encoded-payload>",
"signatures": [
{
"sig": "<base64-encoded-signature>",
"keyid": "<optional-key-id>"
}
]
}
}
```
## 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": "<base64-DER-certificate>"
}
}
```
#### Public Key (alternative to certificate)
```json
{
"publicKey": {
"hint": "<optional-key-hint>",
"rawBytes": "<base64-public-key>"
}
}
```
### Transparency Log Entry
```json
{
"logIndex": "12345",
"logId": {
"keyId": "<base64-log-key-id>"
},
"kindVersion": {
"kind": "dsse",
"version": "0.0.1"
},
"integratedTime": "1703500000",
"inclusionPromise": {
"signedEntryTimestamp": "<base64-SET>"
},
"inclusionProof": {
"logIndex": "12345",
"rootHash": "<base64-merkle-root>",
"treeSize": "100000",
"hashes": ["<base64-hash>", ...],
"checkpoint": {
"envelope": "<checkpoint-note>"
}
},
"canonicalizedBody": "<base64-canonical-body>"
}
```
### DSSE Envelope
Standard DSSE envelope format:
```json
{
"payloadType": "application/vnd.in-toto+json",
"payload": "<base64-encoded-attestation>",
"signatures": [
{
"sig": "<base64-signature>",
"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)