Skip to content

Latest commit

 

History

History
executable file
·
214 lines (166 loc) · 9.4 KB

File metadata and controls

executable file
·
214 lines (166 loc) · 9.4 KB

sigillum

Standalone artefact signing and encrypted-report CLI for the phpboyscout ecosystem.

sigillum is a small command-line tool that does two things for a project's security surface.

It produces and publishes signatures over release artefacts — OpenPGP for checksum manifests, minisign for the artefacts themselves — exposing the ecosystem's sign and keys commands as first-class, top-level commands, the same surface as gtb sign / gtb keys but as a utility you can drop into any release pipeline, Go or not.

It also receives encrypted vulnerability reports. certificate assembles the OpenPGP certificate you publish at your security contact address, and decrypt reads the reports researchers send to it. Both halves of that certificate live in a key service: the private key never leaves it, so decrypting a report is a key-service call rather than a key on a laptop.

The binary's own description string still reads "signing and verification CLI", which the command surface does not bear out: there is no verify command. See What it does not do.

It is built on gtb, but its reason to exist is signing: any non-Go / non-gtb pipeline can install one small binary and sign, with no framework build required.

What it does

  • sigillum sign <input-file> — produce a detached signature over a file using a configured backend: armored OpenPGP (--format openpgp, the default) for checksum manifests, or minisign (--format minisign) for release artefacts. The private key never leaves the HSM/KMS or the local PEM file.
  • sigillum keys generate — generate a fresh keypair locally (Ed25519 or RSA) and emit both halves.
  • sigillum keys mint — mint an ASCII-armored OpenPGP public key from an existing signer (e.g. an AWS KMS key).
  • sigillum keys wkd — generate a Web Key Directory tree from your public keys for external trust-anchor publication.
  • sigillum keys minisign — emit the minisign public key release consumers pin (cargo-binstall, rtb-update).
  • sigillum keys publish — stage a minisign public key into a static keys site with a machine-readable keys.json manifest.
  • sigillum certificate — assemble the OpenPGP certificate to publish at your security contact address, from a certification key and an encryption subkey that both live in a key service. Reproducible: the same --created and the same keys give byte-identical output, because the creation time is hashed into the fingerprint.
  • sigillum decrypt <message> — read a vulnerability report encrypted to that certificate. A message addressed to a different certificate is refused before any key-service call is made.

What it does not do

There is no sigillum verify. sigillum signs and decrypts; verification happens elsewhere — gpg --verify for OpenPGP output, minisign -Vm (or the consumers themselves) for .minisig output, and the Go library gitlab.com/phpboyscout/go/signing/verify for tools checking their own downloads during self-update.

The OpenPGP and minisign paths also need different key algorithms — RSA and Ed25519 respectively — and one key cannot serve both. The full list of limits is in docs/explanation/what-sigillum-does-not-do.md.

Architecture

sigillum is deliberately thin. The signing logic is upstream; the encryption logic is upstream too. sigillum wires the command surface together and ships the backends:

sigillum
   ├─ sign, keys      →  go/signing-cli  →  go/signing  (+ openpgpkey, verify)
   │                         (cobra builders)   (all signing & verification logic)
   │       ├─ go/signing-aws-kms   AWS KMS backend   (blank-imported)
   │       └─ go/signing/local     local PEM backend (blank-imported)
   │
   └─ decrypt,        →  go/encryption   (certificate assembly and parsing,
      certificate           │             ECDH key derivation, key unwrap)
       (sigillum's own      ├─ go/encryption-aws-kms   AWS KMS backend
        pkg/cmd)            └─ go/encryption/local     local PEM backend

The two sides are separate all the way down, including their key-service registries: signing needs a key that signs, decryption needs one that performs ECDH key agreement, and --backend selects from whichever the command needs.

  • go/signing holds all signing/verification logic.
  • go/signing-cli holds only the cobra command builders (sign, keys); it depends on go/signing + cobra and nothing else, so there is no module cycle back to gtb or sigillum.
  • go/encryption holds the OpenPGP certificate assembler and parser, the RFC 6637 key derivation and the AES key unwrap. The decrypt and certificate commands live in sigillum's own pkg/cmd rather than upstream, because they are the only consumers.
  • sigillum attaches those commands to its root and blank-imports the backends it ships. Which backends are compiled in is a build-time decision — a regulated build can drop a blank import and rebuild, and linker dead-code elimination keeps the unused SDK out of the binary.

See docs/explanation/ for the full rationale.

Install

Install the latest release with go install:

go install gitlab.com/phpboyscout/sigillum/cmd/sigillum@latest

The main package lives at cmd/sigillum/, so the install path ends in /cmd/sigillum. Alternatively, download a pre-built binary from the GitLab Releases page.

Quick start

Generate a local keypair, sign a file, and verify it — no cloud account needed:

# 1. Generate a keypair (algorithm is an explicit, required choice)
sigillum keys generate --algorithm rsa --rsa-bits 4096 \
    --name "Test Signer" --email test@example.org \
    --output release.asc --private-output release.pem

# 2. Sign a file with the local backend
sigillum sign --backend local --key-id ./release.pem \
    --public-key ./release.asc checksums.txt   # → checksums.txt.sig

# 3. Verify with gpg
gpg --import release.asc
gpg --verify checksums.txt.sig checksums.txt

For the production AWS KMS path (--backend aws-kms --kms-region … --key-id alias/…) and CI/OIDC integration, see Sign a release artefact.

Documentation

The documentation site source lives in docs/ and follows the Diátaxis framework:

Serve the site locally with just docs-serve.

Prerequisites

  • Go 1.26.5 or newer — required to build and install from source.

The following are only needed for development (each is invoked by a just recipe): just, golangci-lint, pre-commit, zensical (docs site), and goreleaser.

Build & develop

This repository ships a justfile with the common tasks:

just            # tidy + generate + build → bin/sigillum
just build      # the same, explicitly
just install    # install the built binary into $GOPATH/bin

just test       # unit tests with coverage
just test-race  # tests under the race detector
just lint       # golangci-lint
just check      # pre-commit hooks across the tree
just ci         # the full local CI suite (tidy, generate, test, test-race, lint)

Run just ci before opening a merge request — it mirrors what CI runs.

Project layout

Path What lives there
cmd/sigillum/ The main entry point, backend blank-imports (signing.go), and keychain opt-in (keychain.go).
pkg/cmd/root/ The root command — wiring, config loading, and the sign / keys attachment from go/signing-cli.
internal/version/ Build-time version metadata (injected via ldflags).
docs/ The documentation site source (served by zensical).
.gtb/ The gtb generator manifest and ignore rules.

pkg/cmd/root/cmd.go is generated by gtb but then hand-customised to attach the signing commands, so it is marked hands-off in .gtb/ignore. Do not expect gtb regenerate to re-render it.

Contributing

  • Follow Conventional Commits for every commit — the changelog and version bumps are computed from them.
  • Run just ci before opening a merge request.

Releasing

Releases are driven by Conventional Commits and run through the scaffolded GitLab CI pipeline together with GoReleaser. Merging the release cuts the tag and publishes the build artefacts.

License & source