feat(REQ-27): from_sigstore_bundle — ingest cosign/Sigstore bundles (#260) - #264
Open
avrabe wants to merge 1 commit into
Open
feat(REQ-27): from_sigstore_bundle — ingest cosign/Sigstore bundles (#260)#264avrabe wants to merge 1 commit into
avrabe wants to merge 1 commit into
Conversation
…260) varve (#260) already produces cosign bundles (keyless, GitHub-OIDC) but wsc could only verify artifacts it signed itself — SigstoreBundle can emit wsc signatures but nothing converts an existing cosign bundle back into a KeylessSignature. Adds KeylessSignature::from_sigstore_bundle(json) parsing BOTH wire shapes: - Legacy `rekorBundle` JSON (cosign v2.4.x — what varve's v0.28.0 ships): {base64Signature, cert, rekorBundle:{SignedEntryTimestamp, Payload}}. - Protobuf `bundle.sigstore.dev/v0.3+json` envelope (verificationMaterial + messageSignature + tlogEntries). Faithful extraction (verified against two REAL fixtures committed here): - module_hash is read from the hashedrekord body's spec.data.hash.value, never recomputed; the negative-control test flips one hex char and asserts the extracted hash changes. - integratedTime (unix int) -> RFC3339, the form RekorEntry documents and verify_cert_chain parses (confirmed: cert-chain + body-binding both accept the ingested varve bundle). - v0.3 requires a Fulcio certificate; a raw-public-key (non-keyless) bundle is rejected with a specific error, proven on a real cosign v0.3 bundle. Round-trip fidelity test: from_sigstore_bundle -> from_keyless_signature -> to_json -> from_json preserves signature, module_hash, cert chain and rekor fields (uuid/inclusion_proof intentionally empty for legacy — documented). KNOWN LIMITATION → REQ-28 (#231, the verify half): cosign emits ECDSA signatures in ASN.1 DER (varve's is 71 bytes, 3045…), but the offline verifier's verify_crypto uses P256Signature::from_slice (fixed 64-byte P1363), so it currently rejects an ingested DER signature. Making the verifier accept DER (from_der fallback) and handling the empty Rekor uuid on the offline path is REQ-28's scope — that is where "verify an ingested cosign bundle offline" completes. from_sigstore_bundle here is the faithful ingestion half. Fixtures: legacy = varve v0.28.0 public release; v0.3 = real cosign --new-bundle-format output (see fixtures README). Tests: wsc lib 610 pass/3 ignored; sigstore_bundle 7 pass. Refs: #260, #231 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012aR3Md1h46K9wAUWMQiESH
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the ingestion half of #260: wsc could only verify artifacts it signed itself —
SigstoreBundlecan emit wsc signatures but nothing converted an existing cosign bundle back into aKeylessSignature. varve already ships cosign bundles (keyless, GitHub-OIDC).Change
KeylessSignature::from_sigstore_bundle(json)parses both wire shapes:rekorBundleJSON (cosign v2.4.x — varve's v0.28.0 shape).bundle.sigstore.dev/v0.3+jsonenvelope.Verified against two REAL fixtures (committed)
legacy_rekorbundle_keyless.json— varve v0.28.0's actual public bundle. Internally consistent (body digest =sha256(SHA256SUMS.txt)).protobuf_v0.3_localkey.json— realcosign --new-bundle-formatoutput.Faithful extraction, non-vacuously tested:
module_hashread from the hashedrekord body'sspec.data.hash.value, never recomputed — the negative control flips one hex char and asserts the extracted hash changes.integratedTime(unix int) → RFC3339 (the formverify_cert_chainparses; confirmed cert-chain and body-binding both accept the ingested varve bundle).cosign emits ECDSA signatures in ASN.1 DER (varve's is 71 bytes,
3045…), but the offline verifier'sverify_cryptousesP256Signature::from_slice(fixed 64-byte P1363), so it rejects an ingested DER signature today. Making the verifier accept DER (from_derfallback) + handling the empty Rekoruuidon the offline path is REQ-28's scope — that's where "verify an ingested cosign bundle offline" completes. This PR is the faithful ingestion half; it does not claim the ingested bundle fully verifies (and no test says so).Evidence
wsclib 610 pass/3 ignored;sigstore_bundle7 pass; vacuous-oracle gate clean.Part of the v0.12.0 varve-interop line (plan #261). Refs #260, #231.
🤖 Generated with Claude Code