Skip to main content
Version: Next

Sigstore Package

Package sigstore implements blobber.Signer and blobber.Verifier using sigstore-go.

Separate Module

The sigstore package is a separate Go module to isolate dependencies:

import "github.com/meigma/blobber/sigstore"

Users who don't need signing can import github.com/meigma/blobber without pulling in sigstore-go and its transitive dependencies (protobuf, gRPC, OIDC libraries).


Signer

NewSigner

func NewSigner(opts ...SignerOption) (*Signer, error)

Creates a sigstore-based signer.

Parameters:

NameTypeDescription
opts...SignerOptionConfiguration options

Returns:

TypeDescription
*SignerThe configured signer
errorError if configuration fails

Example (keyless):

signer, err := sigstore.NewSigner(
sigstore.WithEphemeralKey(),
sigstore.WithFulcio("https://fulcio.sigstore.dev"),
sigstore.WithRekor("https://rekor.sigstore.dev"),
)

Example (key-based):

signer, err := sigstore.NewSigner(
sigstore.WithPrivateKeyPEM(pemData, nil),
)

Signer Options

WithEphemeralKey

func WithEphemeralKey() SignerOption

Generates a new ephemeral key pair for signing. Use with WithFulcio for keyless signing.

Example:

signer, err := sigstore.NewSigner(
sigstore.WithEphemeralKey(),
sigstore.WithFulcio("https://fulcio.sigstore.dev"),
)

WithPrivateKey

func WithPrivateKey(key crypto.Signer) SignerOption

Uses an existing crypto.Signer for signing.

Parameters:

NameTypeDescription
keycrypto.SignerPrivate key (ECDSA, RSA, or Ed25519)

Supported key types:

TypeMinimum Size
ECDSAP-256, P-384, P-521
RSA2048 bits
Ed25519Standard

Example:

key, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
signer, err := sigstore.NewSigner(
sigstore.WithPrivateKey(key),
)

WithPrivateKeyPEM

func WithPrivateKeyPEM(pemData, password []byte) SignerOption

Parses a PEM-encoded private key and uses it for signing.

Parameters:

NameTypeDescription
pemData[]bytePEM-encoded private key
password[]bytePassword for encrypted keys (nil for unencrypted)

Supported PEM formats:

Block TypeFormat
PRIVATE KEYPKCS#8
RSA PRIVATE KEYPKCS#1
EC PRIVATE KEYSEC1

Example:

pemData, _ := os.ReadFile("private.pem")
signer, err := sigstore.NewSigner(
sigstore.WithPrivateKeyPEM(pemData, nil),
)

With encrypted key:

signer, err := sigstore.NewSigner(
sigstore.WithPrivateKeyPEM(pemData, []byte("password")),
)

WithFulcio

func WithFulcio(baseURL string) SignerOption

Enables certificate issuance via Fulcio CA for keyless signing.

Parameters:

NameTypeDescription
baseURLstringFulcio server URL

Public instance: https://fulcio.sigstore.dev

Example:

signer, err := sigstore.NewSigner(
sigstore.WithEphemeralKey(),
sigstore.WithFulcio("https://fulcio.sigstore.dev"),
)

WithRekor

func WithRekor(baseURL string) SignerOption

Enables transparency log recording via Rekor.

Parameters:

NameTypeDescription
baseURLstringRekor server URL

Public instance: https://rekor.sigstore.dev

Example:

signer, err := sigstore.NewSigner(
sigstore.WithEphemeralKey(),
sigstore.WithFulcio("https://fulcio.sigstore.dev"),
sigstore.WithRekor("https://rekor.sigstore.dev"),
)

Verifier

NewVerifier

func NewVerifier(opts ...VerifierOption) (*Verifier, error)

Creates a sigstore-based verifier.

Parameters:

NameTypeDescription
opts...VerifierOptionConfiguration options

Returns:

TypeDescription
*VerifierThe configured verifier
errorError if configuration fails

Example:

verifier, err := sigstore.NewVerifier(
sigstore.WithIdentity(
"https://accounts.google.com",
"developer@company.com",
),
)

Note: If no identity is specified, the verifier logs a warning and accepts any valid signature. This is unsafe for production.


Verifier Options

WithTrustedRoot

func WithTrustedRoot(tr root.TrustedMaterial) VerifierOption

Sets a custom trusted root for verification.

Parameters:

NameTypeDescription
trroot.TrustedMaterialTrusted root material

Default: Public Sigstore trusted root (fetched on first use)


WithTrustedRootFile

func WithTrustedRootFile(path string) VerifierOption

Loads a trusted root from a JSON file.

Parameters:

NameTypeDescription
pathstringPath to trusted root JSON file

Example:

verifier, err := sigstore.NewVerifier(
sigstore.WithTrustedRootFile("./custom-root.json"),
sigstore.WithIdentity("https://auth.internal", "ci@internal"),
)

WithIdentity

func WithIdentity(issuer, subject string) VerifierOption

Requires signatures from a specific OIDC identity.

Parameters:

NameTypeDescription
issuerstringOIDC provider URL
subjectstringExpected identity

Common issuers:

ProviderIssuer URL
Googlehttps://accounts.google.com
GitHub Actionshttps://token.actions.githubusercontent.com
Microsofthttps://login.microsoftonline.com/{tenant}/v2.0

Example:

verifier, err := sigstore.NewVerifier(
sigstore.WithIdentity(
"https://token.actions.githubusercontent.com",
"https://github.com/org/repo/.github/workflows/release.yml@refs/heads/main",
),
)

WithLogger

func WithLogger(logger *slog.Logger) VerifierOption

Sets a custom logger for the verifier.

Parameters:

NameTypeDescription
logger*slog.LoggerLogger instance

Example:

verifier, err := sigstore.NewVerifier(
sigstore.WithLogger(slog.Default()),
sigstore.WithIdentity("https://accounts.google.com", "user@example.com"),
)

Helper Functions

ParsePrivateKeyPEM

func ParsePrivateKeyPEM(pemData, password []byte) (crypto.Signer, error)

Parses a PEM-encoded private key.

Parameters:

NameTypeDescription
pemData[]bytePEM-encoded private key
password[]bytePassword for encrypted keys

Returns:

TypeDescription
crypto.SignerThe parsed private key
errorError if parsing fails

NewStaticKeypair

func NewStaticKeypair(key crypto.Signer) (*StaticKeypair, error)

Creates a Keypair from an existing crypto.Signer. Used internally by WithPrivateKey.


Complete Examples

Keyless Signing and Verification

package main

import (
"context"
"log"
"os"

"github.com/meigma/blobber"
"github.com/meigma/blobber/sigstore"
)

func main() {
ctx := context.Background()

// Create keyless signer
signer, err := sigstore.NewSigner(
sigstore.WithEphemeralKey(),
sigstore.WithFulcio("https://fulcio.sigstore.dev"),
sigstore.WithRekor("https://rekor.sigstore.dev"),
)
if err != nil {
log.Fatal(err)
}

// Push with signing
pushClient, _ := blobber.NewClient(blobber.WithSigner(signer))
_, err = pushClient.Push(ctx, "ghcr.io/org/config:v1", os.DirFS("./config"))
if err != nil {
log.Fatal(err)
}

// Create verifier with identity requirement
verifier, err := sigstore.NewVerifier(
sigstore.WithIdentity("https://accounts.google.com", "developer@company.com"),
)
if err != nil {
log.Fatal(err)
}

// Pull with verification
pullClient, _ := blobber.NewClient(blobber.WithVerifier(verifier))
err = pullClient.Pull(ctx, "ghcr.io/org/config:v1", "./output")
if err != nil {
log.Fatal(err)
}
}

Key-Based Signing

// Load key from file
pemData, _ := os.ReadFile("private.pem")

signer, err := sigstore.NewSigner(
sigstore.WithPrivateKeyPEM(pemData, nil),
sigstore.WithRekor("https://rekor.sigstore.dev"), // optional transparency
)
if err != nil {
log.Fatal(err)
}

client, _ := blobber.NewClient(blobber.WithSigner(signer))

See Also