Documentation
¶
Overview ¶
Package signing exposes a registry of signing-key backends. Each backend knows how to talk to a specific HSM/KMS/keyring and produce a crypto.Signer that callers (typically package openpgpkey) use to mint an OpenPGP-armored public key.
Backends register themselves at process start via init() calling Register. Downstream binaries opt into a backend by blank-importing its package — this is the same activate-by-side-effect pattern used in net/http/pprof, image/* decoders, and go/credentials/keychain. The signing-key minter (gtb keys mint) reads the registered names via Names() and dispatches based on the --backend flag the user passes.
Built-in backends shipping with the standard `gtb` binary:
- "aws-kms" (gitlab.com/phpboyscout/go/signing-aws-kms): RSA-4096 keys held in AWS KMS.
- "local" (gitlab.com/phpboyscout/go/signing/local): RSA keys loaded from an unencrypted PKCS#1 or PKCS#8 PEM file on disk. Use for the onboarding tutorial / local signing flows; never in CI.
Third parties add backends by implementing Backend and calling Register from their package's init(). No upstream change is needed. See docs/how-to/implement-a-custom-backend.md for the contract details.
API stability: Beta. The interface is small and stable; the only known evolution path is additive (e.g. ECDSA support, capability- discovery methods).
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrUnknownBackend = errors.NewSentinel("signing.unknown_backend", "unknown signing backend")
ErrUnknownBackend is returned by Get when the named backend is not registered. The error message lists the available backends so users can see what their binary actually ships with.
var ErrUnknownBackendType = errors.NewSentinel("signing.unknown_backend_type", "unknown signing backend type")
ErrUnknownBackendType is returned by NewInstance when no factory is registered for the requested type — i.e. the binary was not built with that backend, or the backend does not offer named instances.
Functions ¶
func Names ¶
func Names() []string
Names returns the names of all registered backends, sorted alphabetically. Used by `gtb keys mint --help` to enumerate the accepted --backend values for the current binary.
func Register ¶
func Register(b Backend)
Register adds b to the global backend registry. Called from each backend package's init() so that blank-importing the package activates the backend.
Panics on a duplicate name — duplicates indicate a programming error at process init (two backend packages claiming the same identifier) and failing fast is preferable to silent override.
Panics on a nil Backend or one whose Name() is empty. Both are programmer errors that should never reach a deployed binary.
func RegisterFactory ¶ added in v0.7.0
RegisterFactory records how to construct a NAMED instance of a backend type. A backend package calls it from init(), alongside Register, so that blank-importing the package activates both the default instance and the ability to mint named instances of it.
construct is given the canonical instance name "<type>:<instance>" and must return a Backend whose Name() equals it (NewInstance enforces this). construct runs OUTSIDE the registry lock, so it may itself touch the registry without deadlock.
Panics — all programmer errors that should never reach a deployed binary — on:
- a typeName that is not lowercase kebab-case and colon-free ([a-z0-9][a-z0-9-]*), which the unambiguous selector split relies on;
- a nil construct;
- a duplicate type (one factory per type, mirroring Register's duplicate panic).
A type that offers named instances should also Register a same-key default, so a bare selection of the type resolves and the type appears in Names(); the factory adds the named capability, it does not replace the default.
func ResetForTesting ¶
func ResetForTesting()
ResetForTesting clears the registry — both the registered backends and the instance factories (RegisterFactory). The "ForTesting" suffix is the Go-standard signal that this is a test helper — production code must not call it. Exported (rather than hidden behind a _test.go-only build) so that tests in other packages (notably go/signing-cli's command tests) can drive registry-mutating scenarios against fake backends.
Types ¶
type Backend ¶
type Backend interface {
Name() string
NewSigner(ctx context.Context, keyID string) (crypto.Signer, error)
}
Backend constructs a crypto.Signer for an HSM/KMS-held signing key. Implementations are registered globally via Register and selected at runtime by Name (matching, e.g., a CLI front-end's --backend flag).
The contract is deliberately minimal and CLI-agnostic so a backend is trivial to implement and the module stays dependency-light (no flag library in the core):
- Name returns a stable identifier, unique across the process (duplicate Register calls panic). A registered default is lowercase kebab-case; an instance minted via NewInstance carries the instance-qualified "<type>:<instance>" form (e.g. "aws-kms:prod").
- NewSigner returns a crypto.Signer wrapping the remote key. The backend interprets keyID's format — AWS uses ARNs/aliases, a PEM backend uses a file path, GCP uses resource names, etc. The signer's Public() must return a type the caller can consume; openpgpkey currently requires *rsa.PublicKey.
Backends do not own credential resolution; callers configure the SDK / agent / environment before invoking the signer.
A backend that needs to declare its own CLI flags can implement an optional flag-registration interface defined by the CLI front-end (e.g. gtb), which type-asserts for it. The core intentionally does not define or depend on such an interface, keeping any flag library out of this module.
func Get ¶
Get returns the registered backend with the given name. If no such backend is registered, returns ErrUnknownBackend wrapped with a listing of the available names so the user can immediately see what their binary actually supports.
func NewInstance ¶ added in v0.7.0
NewInstance mints (constructs) a named instance of typeName via its registered factory. It does NOT register the result — the caller owns its lifetime. The canonical name handed to the factory, and required back from it, is "<typeName>:<instance>".
Returns an error on: an empty instance; a type with no factory (ErrUnknownBackendType); a factory error (wrapped); a nil or typed-nil result; or a result whose Name() is not the canonical "<type>:<instance>".
NewInstance validates only these structural invariants. The *grammar* of a selector — the instance character set, the settings shape — belongs to the CLI front-end that parses "<type>:<instance>?…", not here.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package local is the on-disk PEM private-key backend for package signing.
|
Package local is the on-disk PEM private-key backend for package signing. |
|
Package minisign produces and verifies minisign-format detached signatures over release artefacts.
|
Package minisign produces and verifies minisign-format detached signatures over release artefacts. |
|
Package openpgpkey mints an ASCII-armored OpenPGP public key from a crypto.Signer.
|
Package openpgpkey mints an ASCII-armored OpenPGP public key from a crypto.Signer. |
|
Package verify holds the self-update signing primitives.
|
Package verify holds the self-update signing primitives. |