Skip to content

Generate or mint a signing key

There are two ways to obtain the OpenPGP public key file (release.asc) that identifies your signing key:

  • keys generate — create a brand-new keypair locally (both halves), for development, air-gapped signing, or a rotation-authority key.
  • keys mint — derive the armored public key from a private key that already exists elsewhere (an AWS KMS key, or a local PEM). The private half never leaves its HSM/KMS.

Both produce the same kind of release.asc: the identity source you pass to sigillum sign --public-key and publish via WKD.

Generate a fresh keypair

keys generate emits both halves of a new keypair. The algorithm is a required, explicit choice — a signing tool should not silently pick one for you:

sigillum keys generate \
    --algorithm ed25519 \
    --name "Release Signer" --email release@example.org \
    --output release.asc --private-output release.priv.asc

For RSA:

sigillum keys generate \
    --algorithm rsa --rsa-bits 4096 \
    --name "Release Signer" --email release@example.org \
    --output release.asc --private-output release.pem

Notes:

  • --algorithm accepts ed25519 or rsa and has no default — omitting it is an error that lists the valid choices.
  • --rsa-bits (default 4096; 2048/3072/4096 accepted) applies only to RSA and is ignored for Ed25519.
  • --private-output defaults are derived from --output: .asc.priv.asc for Ed25519, .asc.pem for RSA. The RSA .pem is exactly what the local signing backend consumes.
  • --created <rfc3339> pins the creation timestamp for a reproducible key (the timestamp folds into the fingerprint).
  • keys generate refuses to overwrite existing output; pass --force to clobber.

Mint a public key from an existing signer

Use keys mint when the private key already lives in AWS KMS (production) or as a local PEM file. Minting bridges "a crypto.Signer somewhere" to "a valid OpenPGP public key on disk" — it does not generate a private key.

AWS KMS (production)

sigillum keys mint \
    --backend aws-kms \
    --kms-region eu-west-2 \
    --key-id alias/release-signing-v1 \
    --name "Release Signer" --email release@example.org \
    --output release.asc

What happens:

  1. kms:GetPublicKey learns the RSA public half.
  2. An OpenPGP entity is built around it (v4 public-key packet, your User ID, and a positive-cert self-signature). The self-signature is produced by exactly one kms:Sign call — the only time the KMS private half is consulted.
  3. The result is ASCII-armored to --output and the fingerprint is logged at INFO so you can record it in your runbook.

keys mint refuses to overwrite an existing --output; pass --force to re-mint to the same path.

Local PEM (development)

sigillum keys mint \
    --backend local \
    --key-id signing.pem \
    --name "Release Signer" --email release@example.org \
    --output release.asc

This reads signing.pem (unencrypted PKCS#1 or PKCS#8) and writes release.asc the same way. It pairs naturally with keys generate --algorithm rsa, which produces exactly that PEM format.

Reproducibility: --created

Both commands use time.Now() for the OpenPGP creation timestamp by default, and the timestamp folds into the fingerprint. If you must re-derive an existing key (e.g. you lost release.asc but the KMS material is intact), pin --created to the original creation time — same material + same UID + same creation time yields the same fingerprint:

sigillum keys mint ... --created 2026-07-28T00:00:00Z

Smoke-test the result

gpg --show-key --with-fingerprint release.asc
# pub   ...  <date> [SC]
#       <40-char fingerprint>
# uid   Release Signer <release@example.org>

What to do with release.asc

  • Ship it — embed the file in the tool that will verify your releases (its trust set), so verification has an in-binary anchor.
  • Publish it — serve it via WKD so verifiers can cross-check the embedded copy against an externally-administered one.

Both copies must carry the same fingerprint; a verifier that cross-checks them refuses to proceed if they disagree.