# Fulcio/Sigstore Keyless Signing Client ## Module Signer ## Status VERIFIED ## Description Fulcio-based keyless signing using OIDC tokens from CI runners, ephemeral key pairs, short-lived X.509 certificates, DSSE signing, and certificate chain validation. Tests exist for all components. ## Implementation Details - **KeylessDsseSigner**: `src/Signer/__Libraries/StellaOps.Signer.Keyless/KeylessDsseSigner.cs` -- DSSE signer implementing Sigstore keyless workflow: (1) acquire OIDC token via IOidcTokenProvider, (2) generate ephemeral key pair via IEphemeralKeyGenerator, (3) serialize in-toto statement, (4) create proof-of-possession (SHA-256 hash signed with ephemeral key), (5) request short-lived certificate from Fulcio, (6) create DSSE signature using ephemeral key; returns SigningBundle with DsseEnvelope + certificate chain + signing identity metadata - **EphemeralKeyGenerator**: `src/Signer/__Libraries/StellaOps.Signer.Keyless/EphemeralKeyGenerator.cs` -- generates ECDSA P-256 key pairs using .NET crypto APIs; supports EcdsaP256 algorithm; Ed25519 placeholder for future .NET 9+ support - **HttpFulcioClient**: `src/Signer/__Libraries/StellaOps.Signer.Keyless/HttpFulcioClient.cs` -- HTTP client for Fulcio v2 API (`/api/v2/signingCert`): sends OIDC token + public key + proof-of-possession; parses PEM certificate chain from response; extracts OIDC issuer from Fulcio extension OID 1.3.6.1.4.1.57264.1.1; retry logic with exponential backoff; non-retryable errors (400/401/403) vs retryable (5xx) - **SigstoreSigningService**: `src/Signer/StellaOps.Signer/StellaOps.Signer.Infrastructure/Sigstore/SigstoreSigningService.cs` -- orchestrates full Sigstore keyless flow: ephemeral ECDSA P-256 key generation, Fulcio certificate request, artifact signing, Rekor transparency log upload; VerifyKeylessAsync validates signature, certificate validity, and Rekor entry timestamp within certificate window - **IOidcTokenProvider**: `src/Signer/__Libraries/StellaOps.Signer.Keyless/IOidcTokenProvider.cs` -- interface for OIDC token acquisition - **AmbientOidcTokenProvider**: `src/Signer/__Libraries/StellaOps.Signer.Keyless/AmbientOidcTokenProvider.cs` -- CI runner ambient OIDC token detection - **EphemeralKeyPair**: `src/Signer/__Libraries/StellaOps.Signer.Keyless/EphemeralKeyPair.cs` -- disposable key pair model with Sign method - **ICertificateChainValidator**: `src/Signer/__Libraries/StellaOps.Signer.Keyless/ICertificateChainValidator.cs` -- certificate chain validation interface - **FulcioHttpClient**: `src/Signer/StellaOps.Signer/StellaOps.Signer.Infrastructure/Sigstore/FulcioHttpClient.cs` -- infrastructure-level Fulcio client - **RekorHttpClient**: `src/Signer/StellaOps.Signer/StellaOps.Signer.Infrastructure/Sigstore/RekorHttpClient.cs` -- Rekor transparency log HTTP client - **ISigstoreClients**: `src/Signer/StellaOps.Signer/StellaOps.Signer.Infrastructure/Sigstore/ISigstoreClients.cs` -- IFulcioClient and IRekorClient interfaces - **SigstoreOptions**: `src/Signer/StellaOps.Signer/StellaOps.Signer.Infrastructure/Sigstore/SigstoreOptions.cs` -- Fulcio URL, Rekor URL, RequireRekorEntry, retry/backoff config - **Tests**: `src/Signer/StellaOps.Signer/StellaOps.Signer.Tests/Keyless/KeylessDsseSignerTests.cs`, `EphemeralKeyGeneratorTests.cs`, `HttpFulcioClientTests.cs`, `CertificateChainValidatorTests.cs`, `KeylessSigningIntegrationTests.cs` - **Source**: Feature matrix scan ## E2E Test Plan - [x] Verify keyless signing produces a valid DSSE envelope with base64-encoded payload and signature - [x] Verify certificate chain includes leaf certificate from Fulcio and intermediate/root certificates - [x] Verify proof-of-possession is computed as SHA-256 hash of statement signed with ephemeral key - [x] Test Fulcio client retry logic with exponential backoff on 5xx errors - [x] Verify non-retryable Fulcio errors (400/401/403) fail immediately - [x] Test keyless verification validates signature, certificate chain, and Rekor timestamp - [x] Verify signing identity metadata includes OIDC issuer, subject, and certificate expiry - [x] Test ephemeral key disposal after signing completes ## Verification - **Run ID**: run-001 - **Date**: 2026-02-10 - **Method**: Tier 1 code review + Tier 2d existing test verification - **Build**: PASS (0 errors, 0 warnings) - **Tests**: PASS (491/491 signer tests pass) - **Code Review**: - KeylessDsseSigner: Full keyless workflow verified -- OIDC token acquisition, ephemeral key generation, proof-of-possession creation, Fulcio certificate request, DSSE envelope construction. Returns complete SigningBundle with envelope + certificate chain + identity metadata. - EphemeralKeyGenerator: ECDSA P-256 key pair generation using .NET ECDsa.Create(ECCurve.NamedCurves.nistP256). Disposable pattern correctly implemented. Ed25519 placeholder returns NotSupportedException. - HttpFulcioClient: Fulcio v2 API integration verified. PEM parsing, OID extraction (1.3.6.1.4.1.57264.1.1), retry with exponential backoff, non-retryable status code detection. - SigstoreSigningService: End-to-end orchestration of keyless signing + Rekor upload. VerifyKeylessAsync correctly validates signature, certificate chain, and Rekor timestamp within certificate validity window. - Tests: KeylessDsseSignerTests (mock-based unit tests), EphemeralKeyGeneratorTests (crypto validation), HttpFulcioClientTests (HTTP interaction tests), CertificateChainValidatorTests (chain validation), KeylessSigningIntegrationTests (end-to-end flow with test doubles). - **Verdict**: PASS