signer

package
v0.0.41 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 19, 2026 License: Apache-2.0 Imports: 39 Imported by: 0

Documentation

Overview

Package signer signs OCI artifacts with Sigstore, following the cosign convention: a "simple signing" payload binding the artifact's manifest digest is signed, attached to the registry as a cosign signature manifest (the "sha256-<hex>.sig" tag), and returned as a serialized Sigstore bundle for durable storage and offline re-verification.

Both cosign signing methods are supported, selected by Options: a file-based key pair (Options.Key) or keyless signing against Fulcio and Rekor with an OIDC identity token (Options.IdentityToken). Acquiring that token — ambient CI credentials, an interactive browser flow, a device flow — is entirely the caller's concern; this package never performs OAuth and only ever forwards the token it is handed to Fulcio.

It is the signing counterpart to github.com/stacklok/toolhive-core/container/verifier: a key-signed bundle produced here verifies through that package's verifier.VerifyBundleWithKey and a keyless one through verifier.VerifyBundle, and the attached manifest is the layout verifier.RetrieveBundles reconstructs from.

Index

Constants

View Source
const (
	// DefaultFulcioURL is the public-good Fulcio certificate authority.
	DefaultFulcioURL = "https://fulcio.sigstore.dev"
	// DefaultRekorURL is the public-good Rekor transparency log.
	DefaultRekorURL = "https://rekor.sigstore.dev"
)

Public-good Sigstore endpoints, used when Options leaves the corresponding URL empty.

These are hardcoded rather than derived from a trusted root, deliberately. The trusted root does carry the deployment's URIs, but reading them means fetching a root (a TUF network round trip, or the point-in-time snapshot embedded in container/verifier) purely to learn a URL, and the URI is only reachable by type-asserting root.CertificateAuthority — a single-method Verify interface — to the concrete *root.FulcioCertificateAuthority. More importantly, the trusted root is verification material: keying signing endpoints off it would let a trust-root refresh silently redirect where signing requests, and the identity token in them, are sent. Signing against a different deployment is instead an explicit choice, made through Options.

Variables

View Source
var ErrAmbiguousSigningMethod = errors.New(
	"conflicting signing methods: set exactly one of Options.Key or Options.IdentityToken")

ErrAmbiguousSigningMethod indicates both Options.Key and Options.IdentityToken were set. Rather than pick one, signing fails: the two produce materially different trust material — a bundle verifiers check against a bare public key, versus one they check against a Fulcio identity and the transparency log — so silently choosing would attach a signature the caller cannot verify the way it expects.

View Source
var ErrKeyRequired = errors.New(
	"no signing method provided: set Options.Key to a cosign private key, " +
		"or Options.IdentityToken to an OIDC identity token for keyless signing")

ErrKeyRequired indicates no signing method was provided: signing needs either a cosign private key or an OIDC identity token for the keyless flow. Callers exposing a CLI should wrap this with the flags the user is expected to pass.

Functions

func PayloadDigest

func PayloadDigest(imageRef, digestStr string) (string, error)

PayloadDigest returns the digest of the simple-signing payload that a signature over the artifact at ref pinned to digestStr covers.

Consumers verifying a stored bundle generally hold only the reference and the artifact digest — not the Result from signing — so this is the supported way to recover the value a bundle verifier needs.

func SimpleSigningPayload

func SimpleSigningPayload(imageRef, digestStr string) ([]byte, error)

SimpleSigningPayload builds the canonical simple-signing payload for the artifact at ref pinned to digestStr. This payload — not the manifest digest — is what gets signed, per the cosign convention: a verifier recovers the payload from the signature manifest's layer, checks the signature over it, and reads the bound manifest digest out of it. Exported because offline re-verification of a stored key-signed bundle must reconstruct exactly these bytes to check the signature's binding.

Types

type Default

type Default struct {
	// contains filtered or unexported fields
}

Default implements Signer for both cosign signing methods: file-based key pairs and keyless signing via Fulcio and Rekor.

func NewDefault

func NewDefault(keychain authn.Keychain) *Default

NewDefault creates a signer using the given registry auth keychain for pushing the signature manifest. A nil keychain falls back to the default keychain.

func (*Default) SignOCI

func (d *Default) SignOCI(ctx context.Context, ref, digestStr string, opts Options) (*Result, error)

SignOCI signs the artifact following the cosign convention: the signature is computed over the simple-signing payload (which embeds the manifest digest, binding the signature to the artifact), the SAME signature is attached to the registry as a cosign signature manifest, and the returned bundle carries it with the payload's digest as the signed message. A verifier reconstructing the bundle from the registry manifest (or re-verifying the stored bundle offline) therefore checks exactly the signature that was attached — one signature, two representations.

The signing method comes from opts: a file key, or keyless via Fulcio and Rekor. The two differ only in where the signing key and its trust material come from — everything downstream of sign.Bundle, including the attached manifest layout, is shared.

type Options

type Options struct {
	// Key is the path to a cosign PEM-encoded private key file. An
	// encrypted key is decrypted with the COSIGN_PASSWORD environment
	// variable, matching the cosign CLI.
	Key string
	// IdentityToken is a raw OIDC ID token (a JWT, as a plain string)
	// identifying the signer to Fulcio. Setting it selects the keyless
	// flow: a single-use ephemeral key pair is minted, Fulcio issues a
	// short-lived certificate binding it to the token's identity, and the
	// signature is submitted to Rekor. Obtaining the token is the caller's
	// responsibility — see the package doc.
	//
	// This token is sent as a bearer credential to FulcioURL, which is why
	// FulcioURL and RekorURL are validated to be HTTPS (loopback excepted,
	// for tests) before either is contacted — see keylessBundleOptions.
	IdentityToken string
	// FulcioURL overrides the certificate authority for keyless signing.
	// Empty means DefaultFulcioURL. Defaulting happens at signing time and
	// only when IdentityToken selects the keyless flow — a zero Options
	// value alone still errors with ErrKeyRequired, it does not sign
	// against the public-good deployment by default. Once IdentityToken IS
	// set, though, an empty FulcioURL/RekorURL is a deliberate posture
	// change from "no key ⇒ always error": keyless signing then performs
	// outbound network egress to public-good Sigstore services by default.
	FulcioURL string
	// RekorURL overrides the transparency log for keyless signing. Empty
	// means DefaultRekorURL, applied at signing time as with FulcioURL.
	// Only the Rekor v1 API is supported — see rekorAPIVersionV1.
	//
	// A Rekor entry is not optional: the verification policy this project's
	// container/verifier applies to keyless bundles requires a
	// transparency-log entry, so a bundle signed without one would not
	// verify.
	RekorURL string
}

Options configures OCI signing. Exactly one signing method must be set: Key for the cosign key-pair flow, or IdentityToken for keyless signing. FulcioURL and RekorURL apply to keyless signing only and are ignored for the key-pair flow.

type Result

type Result struct {
	// Bundle is the serialized Sigstore bundle, for durable storage and
	// later offline re-verification.
	//
	// Its JSON shape is not stable across calls for the same identity: a
	// freshly attached signature serializes as sign.Bundle's own bundle
	// media type (v0.3), while a signature this call deduped against (see
	// SignOCI's "one signature, two representations" doc) is reconstructed
	// by verifier.RetrieveBundles from the classic cosign annotations —
	// the v0.1 shape, carrying an inclusion promise rather than a proof.
	// Both verify identically; a caller comparing stored bundles byte-for-
	// byte across calls, or inspecting mediaType, will see this difference.
	Bundle []byte
	// PayloadDigest is the "<algorithm>:<hex>" digest of the simple-signing
	// payload the bundle actually signs.
	//
	// This is deliberately surfaced because it is NOT the artifact digest
	// passed to SignOCI. Following the cosign convention, the signature
	// covers a payload that *embeds* the artifact digest rather than the
	// digest itself, so verifying Bundle offline requires this value —
	// passing the artifact digest to a bundle verifier will always fail.
	// See [PayloadDigest] to recompute it from a reference and digest alone.
	PayloadDigest string
}

Result is the outcome of a signing operation.

type Signer

type Signer interface {
	// SignOCI signs the artifact at ref pinned to the given manifest digest
	// ("sha256:..."), attaches the signature as a cosign signature manifest
	// next to the artifact, and returns the bundle together with the digest
	// it signs.
	SignOCI(ctx context.Context, ref, digest string, opts Options) (*Result, error)
}

Signer signs OCI artifacts and attaches the signature to the registry.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL