8.1 KiB
8.1 KiB
Signed SBOM Archive Specification
Version: 1.0.0 Status: Draft Last Updated: 2026-01-15
Overview
This specification defines a self-contained, cryptographically signed SBOM archive format that bundles:
- The SBOM document (SPDX or CycloneDX)
- DSSE signature envelope
- Verification materials (certificates, transparency proofs)
- Metadata (tool versions, timestamps)
- Offline verification resources
Archive Structure
signed-sbom-{digest_short}-{timestamp}.tar.gz
|
+-- sbom.spdx.json # OR sbom.cdx.json (CycloneDX)
+-- sbom.dsse.json # DSSE envelope containing signature
+-- manifest.json # Archive inventory with hashes
+-- metadata.json # Generation metadata
+-- certs/
| +-- signing-cert.pem # Signing certificate
| +-- signing-chain.pem # Full certificate chain
| +-- fulcio-root.pem # Fulcio root CA (for keyless)
+-- rekor-proof/ # Optional: transparency log proof
| +-- inclusion-proof.json
| +-- checkpoint.sig
| +-- rekor-public.pem
+-- schemas/ # Bundled validation schemas
| +-- spdx-2.3.schema.json
| +-- spdx-3.0.1.schema.json
| +-- cyclonedx-1.7.schema.json
| +-- dsse.schema.json
+-- VERIFY.md # Human-readable verification guide
File Specifications
sbom.spdx.json / sbom.cdx.json
The primary SBOM document in either:
- SPDX: Versions 2.3 or 3.0.1 (JSON format)
- CycloneDX: Versions 1.4, 1.5, 1.6, or 1.7 (JSON format)
Requirements:
- UTF-8 encoding without BOM
- Canonical JSON formatting (RFC 8785 compliant)
- No trailing whitespace or newlines
sbom.dsse.json
DSSE envelope containing the SBOM signature:
{
"payloadType": "application/vnd.stellaops.sbom+json",
"payload": "<base64-encoded-sbom>",
"signatures": [
{
"keyid": "SHA256:abc123...",
"sig": "<base64-encoded-signature>"
}
]
}
manifest.json
Archive inventory with integrity hashes:
{
"schemaVersion": "1.0.0",
"archiveId": "signed-sbom-abc123-20260115T123456Z",
"generatedAt": "2026-01-15T12:34:56Z",
"files": [
{
"path": "sbom.spdx.json",
"sha256": "abc123...",
"size": 45678,
"mediaType": "application/spdx+json"
},
{
"path": "sbom.dsse.json",
"sha256": "def456...",
"size": 1234,
"mediaType": "application/vnd.dsse+json"
}
],
"merkleRoot": "sha256:789abc...",
"totalFiles": 12,
"totalSize": 98765
}
metadata.json
Generation and tool metadata:
{
"schemaVersion": "1.0.0",
"stellaOps": {
"suiteVersion": "2027.Q1",
"scannerVersion": "1.2.3",
"scannerDigest": "sha256:scanner-image-digest",
"signerVersion": "1.0.0",
"sbomServiceVersion": "1.1.0"
},
"generation": {
"timestamp": "2026-01-15T12:34:56Z",
"hlcTimestamp": "1737000000000000000",
"operator": "build@company.com"
},
"input": {
"imageRef": "registry.company.com/app:v1.0.0",
"imageDigest": "sha256:image-digest-here",
"platform": "linux/amd64"
},
"sbom": {
"format": "spdx-2.3",
"componentCount": 142,
"packageCount": 89,
"fileCount": 1247
},
"signature": {
"type": "keyless",
"issuer": "https://accounts.google.com",
"subject": "build@company.com",
"signedAt": "2026-01-15T12:34:57Z"
},
"reproducibility": {
"deterministic": true,
"expectedDigest": "sha256:expected-sbom-digest"
}
}
VERIFY.md
Human-readable verification instructions:
# SBOM Archive Verification
## Quick Verification
```bash
# Verify archive integrity
sha256sum -c <<EOF
abc123... sbom.spdx.json
def456... sbom.dsse.json
EOF
# Verify signature using cosign
cosign verify-blob \
--signature sbom.dsse.json \
--certificate certs/signing-cert.pem \
--certificate-chain certs/signing-chain.pem \
sbom.spdx.json
Offline Verification
# Using bundled Fulcio root
cosign verify-blob \
--signature sbom.dsse.json \
--certificate certs/signing-cert.pem \
--certificate-chain certs/signing-chain.pem \
--certificate-oidc-issuer https://accounts.google.com \
--offline \
sbom.spdx.json
Rekor Inclusion Proof
# Verify transparency log inclusion
rekor-cli verify \
--artifact sbom.spdx.json \
--signature sbom.dsse.json \
--public-key certs/signing-cert.pem \
--rekor-server https://rekor.sigstore.dev
## Cryptographic Requirements
### Hash Algorithms
| Purpose | Algorithm | Format |
|---------|-----------|--------|
| File hashes | SHA-256 | Lowercase hex |
| Merkle tree | SHA-256 | Lowercase hex with `sha256:` prefix |
| Certificate fingerprint | SHA-256 | Uppercase hex with colons |
### Signature Algorithms
Supported signature algorithms:
- **ECDSA-P256**: Recommended for keyless (Fulcio)
- **ECDSA-P384**: High-security environments
- **RSA-PSS-4096**: Legacy compatibility
- **Ed25519**: High-performance signing
### DSSE Envelope
DSSE (Dead Simple Signing Envelope) per specification:
- PAE (Pre-Authentication Encoding) for signing
- Base64 encoding for payload and signatures
- Multiple signatures supported for threshold signing
## Verification Process
### Step 1: Archive Integrity
```python
# Verify tar.gz integrity
import tarfile
import hashlib
with tarfile.open("signed-sbom.tar.gz", "r:gz") as tar:
manifest = json.load(tar.extractfile("manifest.json"))
for file_entry in manifest["files"]:
content = tar.extractfile(file_entry["path"]).read()
actual_hash = hashlib.sha256(content).hexdigest()
assert actual_hash == file_entry["sha256"]
Step 2: Signature Verification
# Verify DSSE signature
from sigstore.verify import Verifier
verifier = Verifier.production()
result = verifier.verify(
artifact=sbom_content,
signature=dsse_envelope,
certificate=signing_cert
)
assert result.success
Step 3: Certificate Chain Validation
# Validate certificate chain
from cryptography import x509
chain = load_certificate_chain("certs/signing-chain.pem")
root = load_certificate("certs/fulcio-root.pem")
validate_chain(chain, root)
Step 4: Transparency Log (Optional)
# Verify Rekor inclusion
from rekor_client import verify_inclusion
result = verify_inclusion(
artifact_hash=sbom_hash,
proof=inclusion_proof,
checkpoint=checkpoint
)
assert result.verified
Compatibility
SBOM Formats
| Format | Version | Status |
|---|---|---|
| SPDX | 2.3 | Supported |
| SPDX | 3.0.1 | Supported |
| CycloneDX | 1.4 | Supported |
| CycloneDX | 1.5 | Supported |
| CycloneDX | 1.6 | Supported |
| CycloneDX | 1.7 | Supported |
Compression
| Format | Extension | Status |
|---|---|---|
| gzip | .tar.gz | Default |
| zstd | .tar.zst | Recommended (smaller) |
| none | .tar | Supported |
API Endpoint
GET /scans/{scanId}/exports/signed-sbom-archive
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
| format | string | spdx-2.3 | SBOM format |
| compression | string | gzip | Compression type |
| includeRekor | bool | true | Include Rekor proof |
| includeSchemas | bool | true | Bundle JSON schemas |
Response Headers:
| Header | Description |
|---|---|
| Content-Type | application/gzip or application/zstd |
| Content-Disposition | attachment; filename="signed-sbom-{digest}.tar.gz" |
| X-SBOM-Digest | SHA-256 of SBOM content |
| X-Archive-Merkle-Root | Merkle root of archive |
| X-Rekor-Log-Index | Rekor log index (if applicable) |
Security Considerations
- Determinism: All outputs must be reproducible given same inputs
- Canonicalization: JSON must be RFC 8785 canonical before signing
- Time sources: Use injected TimeProvider, not system clock
- Key material: Never include private keys in archives
- Offline verification: Bundle all necessary verification materials