keysigner

package
v1.0.98 Latest Latest
Warning

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

Go to latest
Published: Oct 13, 2026 License: MIT Imports: 29 Imported by: 0

Documentation

Overview

Package keysigner provides stable handles for signing keys. L1/L2 backends keep private material inside platform security services; the L3 backend decrypts an encrypted file in-process using a caller-supplied secret. Callers can obtain the public key and request signatures but cannot export private material through this API. ES256 is the default. SoftwareSigner also supports ES384, ES512, EdDSA, and RS256. Native adapters accept only algorithms implemented by their platform API; Apple's Secure Enclave is P-256 only.

Index

Constants

View Source
const (
	// AlgES256 is ECDSA with P-256 and SHA-256.
	AlgES256 = "ES256"
	// AlgES384 is ECDSA with P-384 and SHA-384.
	AlgES384 = "ES384"
	// AlgES512 is ECDSA with P-521 and SHA-512.
	AlgES512 = "ES512"
	// AlgEdDSA is EdDSA with Ed25519.
	AlgEdDSA = "EdDSA"
	// AlgRS256 is RSA PKCS#1 v1.5 with SHA-256 and a key of at least 2048 bits.
	AlgRS256 = "RS256"
)
View Source
const (
	MacOSSecureEnclaveSignerName = "macos-secure-enclave"
	MacOSKeychainSignerName      = "macos-keychain"
	WindowsPlatformKSPSignerName = "windows-platform-ksp"
	WindowsSoftwareKSPSignerName = "windows-software-ksp"
	LinuxTPMSignerName           = "linux-tpm"
	SoftwareSignerName           = "software-file"
)

Stable backend names used by stored key metadata and backend directories.

Variables

View Source
var (
	// ErrUnavailable means this signer cannot be used on this build or host.
	// Only new bindings may try another signer; existing bindings fail closed.
	ErrUnavailable = errors.New("key signer is unavailable")
	// ErrCleanupFailed prevents fallback after incomplete rollback or state restoration.
	ErrCleanupFailed = errors.New("key signer cleanup failed")
	// ErrKeyNotFound means the stable handle no longer resolves to its private
	// key. Callers must never recreate a key for an existing token binding.
	ErrKeyNotFound    = errors.New("signing key not found")
	ErrKeyExists      = errors.New("signing key already exists")
	ErrCorrupt        = errors.New("invalid or mismatched signing key record")
	ErrUnlock         = errors.New("wrong unlock secret or damaged signing key ciphertext")
	ErrUnlockRequired = errors.New("software signing requires a 32-byte cryptographically random unlock secret")
	// ErrUnsupportedAlgorithm rejects an algorithm without accessing key storage.
	ErrUnsupportedAlgorithm = errors.New("unsupported signing algorithm")
)

Functions

func AlgForKey

func AlgForKey(public crypto.PublicKey) (string, error)

AlgForKey returns the JOSE algorithm for a validated public signing key.

func CanFallback

func CanFallback(err error) bool

CanFallback reports whether a new binding may try another backend. Cancellation and incomplete cleanup always take precedence over unavailability.

func EncodePublicKey

func EncodePublicKey(public crypto.PublicKey) (string, error)

EncodePublicKey returns a validated public signing key as standard-base64 PKIX DER.

func P256PublicKey

func P256PublicKey(public crypto.PublicKey) (*ecdsa.PublicKey, error)

P256PublicKey validates and projects a backend public key to P-256 ECDSA.

func PlatformSignerNames

func PlatformSignerNames() []string

PlatformSignerNames returns the ordered native backends for the current OS.

func ProbeSigner

func ProbeSigner(ctx context.Context, signer Signer, ref KeyRef, input []byte) (err error)

ProbeSigner verifies one signer's create/sign/delete path without retaining the probe key.

func PublicKeyThumbprint

func PublicKeyThumbprint(public crypto.PublicKey) (string, error)

PublicKeyThumbprint returns an RFC 7638 SHA-256 JWK thumbprint.

Types

type KeyCreator

type KeyCreator interface {
	CreateKey(ctx context.Context, ref KeyRef) (crypto.PublicKey, error)
}

KeyCreator optionally supports creation without reusing an existing identity.

type KeyRef

type KeyRef struct {
	Label string
	// Algorithm is the required JOSE signing algorithm; empty means AlgES256.
	// It is not part of the label's identity and must never replace an existing key.
	Algorithm string
}

KeyRef is a stable backend handle.

type PublicJWK

type PublicJWK struct {
	Kty string `json:"kty"`
	Crv string `json:"crv,omitempty"`
	X   string `json:"x,omitempty"`
	Y   string `json:"y,omitempty"`
	N   string `json:"n,omitempty"`
	E   string `json:"e,omitempty"`
}

PublicJWK contains the public members of a supported signing key.

func PublicKeyJWK

func PublicKeyJWK(public crypto.PublicKey) (PublicJWK, error)

PublicKeyJWK returns only the public key members of a validated signing key.

func (PublicJWK) Map

func (j PublicJWK) Map() map[string]any

Map returns a mutable JSON object containing only populated JWK members.

type SecurityLevel

type SecurityLevel string

SecurityLevel is the protection class of a signing backend.

const (
	SecurityLevelL1 SecurityLevel = "L1"
	SecurityLevelL2 SecurityLevel = "L2"
	SecurityLevelL3 SecurityLevel = "L3"
)

type Signer

type Signer interface {
	// Name identifies the exact backend used to restore an existing binding.
	Name() string
	SecurityLevel() SecurityLevel
	// EnsureKey is only for new bindings. Existing bindings must use PublicKey
	// and Sign, which never create replacements. KeyCreator rejects duplicates.
	EnsureKey(ctx context.Context, ref KeyRef) (crypto.PublicKey, error)
	PublicKey(ctx context.Context, ref KeyRef) (crypto.PublicKey, error)
	Sign(ctx context.Context, ref KeyRef, signingInput []byte) (signature []byte, algorithm string, err error)
	// DeleteKey removes a key; missing keys may return nil or ErrKeyNotFound.
	DeleteKey(ctx context.Context, ref KeyRef) error
}

Signer owns signing keys behind stable references. Sign hashes signingInput as required by ref.Algorithm and returns a JOSE signature and that algorithm.

func EnsureKeyWithFallback

func EnsureKeyWithFallback(ctx context.Context, signers []Signer, ref KeyRef) (Signer, crypto.PublicKey, error)

EnsureKeyWithFallback creates or opens a key with the strongest usable signer. It falls through only when a backend is unavailable.

func NewPlatformSigners

func NewPlatformSigners(directory func(string) (string, error)) []Signer

NewPlatformSigners constructs the current OS's native backends in fallback order. Storage location remains caller policy through directory.

func NewSigner

func NewSigner(name string, directory func(string) (string, error)) Signer

NewSigner constructs only the named native backend, or returns nil if this platform does not support it. The resolver receives the signer name when a key operation starts.

func NewSoftwareSigner

func NewSoftwareSigner(directory string, unlock func(context.Context) ([]byte, error)) (Signer, error)

NewSoftwareSigner explicitly enables L3 in a caller-selected local directory. Unlock returns a fresh buffer containing a 32-byte cryptographically random secret, cleared after derivation. Keep it apart from key files; passwords are not supported. The caller owns secret storage and backend fallback policy.

Jump to

Keyboard shortcuts

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