Add Rekor v2 support, DSSE/in-toto signing, and managed-key verification (v0.3.0)#308
Open
segiddins wants to merge 11 commits into
Open
Add Rekor v2 support, DSSE/in-toto signing, and managed-key verification (v0.3.0)#308segiddins wants to merge 11 commits into
segiddins wants to merge 11 commits into
Conversation
0a1814d to
5b99bcd
Compare
…tion Bump sigstore-conformance to v0.0.29 and tuf-conformance to v2.4.0. Fix issues surfaced by the newer suite: - Treat the OIDC nbf claim as optional (RFC 7519), which was rejecting beacon tokens that omit it and breaking all signing. - Reject message-signature bundles whose messageDigest hint does not match the artifact being verified. Add verification support for Rekor v2 (tiled) transparency log bundles: - Parse Ed25519 (PKIX_ED25519) log keys, and key the Rekor keyring by the trusted root's declared log id, since a Rekor v2 log id is a C2SP signed-note key hash over the log name rather than a digest of the key. - Verify hashedrekord 0.0.2 entries (including the hashedrekord-over-DSSE encoding) directly against the bundle's artifact, signature, and cert. - Rely on the Timestamping Service for signing time, as Rekor v2 entries carry no integrated time; require at least one trusted timestamp. - Ignore unknown witness cosignatures on checkpoints, requiring one valid signature from the log key. - Verify the RFC 3161 message imprint against the bundle signature and enforce the timestamp authority's validity window from the trusted root. Repoint the conformance unit tests to the reorganized bundle-verify/ asset layout, verifying offline against the vendored production trusted root. Mark only the remaining unsupported conformance cases as xfail: managed-key verification and signing to a Rekor v2 instance. Signed-off-by: Samuel Giddins <segiddins@segiddins.me>
Signed-off-by: Samuel Giddins <segiddins@segiddins.me>
Signed-off-by: Samuel Giddins <segiddins@segiddins.me>
Support verifying bundles whose verificationMaterial is a public key hint rather than a Fulcio certificate. The verifying key is supplied out-of-band via a new `--key` flag; certificate-path validation, SCT verification, and identity-policy checks are skipped, while the signature and its binding to the Rekor entry are still verified against the supplied key. Signed-off-by: Samuel Giddins <segiddins@segiddins.me>
Bump the protobug_sigstore_protos dependency from ~> 0.1.0 to ~> 0.2.0, which pulls in protobuf-specs v0.5.1. Take advantage of two additions the new specs ship: - SigningConfig v0.2 is now a compiled message, so signing_config.rb decodes the document through Sigstore::TrustRoot::V1::SigningConfig instead of parsing the JSON by hand. Only the service-selection algorithm (per-operator collapse + ANY/EXACT/ALL selector) remains in Ruby. An unset EXACT count now defaults to the proto zero value, which the selector logic rejects as invalid. - Artifact gained a typed artifact_digest oneof variant. VerificationInput now accepts it alongside the raw-bytes and sha256: URI forms, extracted into a testable VerificationInput.hashed_input_for. Signed-off-by: Samuel Giddins <segiddins@segiddins.me>
Implement signing an in-toto statement as a DSSE envelope, the last conformance signing case sigstore-ruby did not support. `sign-bundle --in-toto` now signs the file's DSSE Pre-Authentication Encoding, wraps it in an io.intoto.Envelope, and submits the transparency-log entry as a Rekor v1 `dsse` 0.0.1 entry (or, against a Rekor v2 instance, a hashedrekord over the PAE digest, matching the verification side). The bundle carries the envelope rather than a message signature, and is self-verified against the statement's first subject digest. Drop the managed-key xfails from the Rakefile and ci.yml: managed-key verification has been supported since the previous commit, so those cases now pass and were failing CI as strict XPASS. The full conformance suite now passes with no xfails beyond the conditional TSA timestamp case. Signed-off-by: Samuel Giddins <segiddins@segiddins.me>
Add the protobug_in_toto_attestation_protos dependency and decode the in-toto statement through InTotoAttestation::V1::Statement in the DSSE self-verification path, instead of parsing the JSON by hand. Default the signing config from TUF when none is given. SigningConfig gains production/staging/from_tuf (mirroring TrustedRoot) backed by a new TrustUpdater#signing_config_path that fetches the signing_config.v0.2.json target, returning nil when the repository publishes none or when offline. The CLI's sign command now falls back to this published config instead of nil, so signing targets whatever Rekor the instance's config selects -- Rekor v2 where the config lists a valid v2 service -- and picks up the instance's TSA. With no published config (or offline) the Signer still uses the legacy v1 flow from the trusted root. Both TrustedRoot and SigningConfig also gain a from_tuf_updater entry point that builds from an already-refreshed updater, and the CLI shares one TrustUpdater between them so signing refreshes the repository once rather than twice. Signed-off-by: Samuel Giddins <segiddins@segiddins.me>
Backfill CHANGELOG entries for 0.2.0-0.2.3 and add a 0.3.0 entry covering Rekor v2, DSSE/in-toto signing, managed-key verification, TSA signing, and the protobuf-specs v0.5.1 upgrade. Signed-off-by: Samuel Giddins <segiddins@segiddins.me>
The extremely-dangerous-public-oidc-beacon action is deprecated and already fails
to publish a usable token ("Current token expires too early"), breaking the CI
smoketest. Fetch sigstore-conformance's longer-lived public test token directly
instead; it is issued by a Google service account, so make the smoketest's expected
certificate OIDC issuer configurable (defaulting to GitHub Actions for the ambient
identity used when releasing).
Signed-off-by: Samuel Giddins <segiddins@segiddins.me>
Three fixes surfaced by the ruby-head and jruby-head CI legs: - Pass +verifier_pem+ to Bundle#expected_tlog_entry positionally instead of as a keyword argument. JRuby 4.0 (jruby-head) mis-binds the keyword through the bundle's DelegateClass and raises ArgumentError; the helpers it forwards to are already positional, so this is also more consistent. - On JRuby, compute the precertificate TBS via the manual ASN.1 path rather than OpenSSL::X509::Certificate#tbs_bytes. jruby-openssl's tbs_bytes does not honor removing the SCT extension, producing the wrong TBS and breaking SCT verification. - Bump the bundled Bundler to 4.0.14. 2.6.9 crashes during 'bundle install' on Ruby 4.1 (ruby-head) with 'uninitialized constant Pathname::SEPARATOR_PAT'; 4.0.14 requires Ruby >= 3.2 and installs the existing lockfile unchanged. Signed-off-by: Samuel Giddins <segiddins@segiddins.me>
daea6da to
cf6c27c
Compare
The jruby-head TUF conformance leg failed with XPASS(strict) on test_keytype_and_scheme[rsa/rsassa-pss-sha256]. The xfail set keyed the RSASSA-PSS case on RUBY_ENGINE == "jruby", but the library actually gates PSS verification on OpenSSL::PKey::RSA#verify_pss (internal/key.rb). Stable jruby's jruby-openssl lacks the method so the case fails as expected, while jruby-head's newer jruby-openssl provides it, so verification succeeds and pytest's strict xfail turns the unexpected pass into a job failure. Gate the xfail on the same capability instead of the engine name: emit it only when verify_pss is undefined. This drops the jruby special-case entirely and self-corrects whenever stable jruby gains the method. Signed-off-by: Samuel Giddins <segiddins@segiddins.me>
kares
reviewed
Jun 25, 2026
| # precertificate SCT extension (it re-encodes the original extensions), yielding | ||
| # the wrong TBS and breaking SCT verification. Fall through to the manual ASN.1 | ||
| # path on JRuby, which manipulates the DER directly and is engine-independent. | ||
| if openssl.respond_to?(:tbs_bytes) && RUBY_ENGINE != "jruby" |
There was a problem hiding this comment.
JRuby has pushed jruby-openssl 0.16.1 with a fix; should this be re-evauluated?
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.
This stack brings sigstore-ruby up to current sigstore protocol support and prepares a
0.3.0release.What's included
hashedrekord0.0.2 entry type. v2 entries carry no integrated time and no online retrieval API, so the binding to the log rests entirely on the Merkle inclusion proof and its checkpoint signature, which are now verified for every checkpoint-bearing entry. Ed25519 log ids are derived as C2SP note key hashes from the trusted root's declaredlogId.Signer#sign_dsse), using the in-toto attestation protos.Verifier#verify(key:), for bundles that carry a public-key hint instead of a Fulcio certificate. The certificate path validation, SCT, and identity-policy steps are skipped only for such bundles (gated on the bundle's structuralkey_based?), and a mutual-exclusion guard rejects key-without-cert-bundle and cert-bundle-with-key.protobug_in_toto_attestation_protosdependency and wideningprotobug_sigstore_protosto~> 0.2.0.Security hardening
gen_timefalls within the Timestamping Authority's validity window. Verification fails closed when no trusted signing time (TSA response or log integrated time) is available.NoMethodError.EXACTsigning-service selector now accepts configs that list more services than requested, matching the spec / sigstore-python.Notes
0.3.0and backfills the changelog (including the previously unrecorded 0.2.x releases).Marked draft pending CI (including the conformance jobs against prod and staging).