Command-line tool for generating signing keys and signing/verifying Go plugins with cryptographic signatures.
go install github.com/altessa-s/go-atlas/cmd/plugin-sign@latestplugin-sign is a verb-style CLI:
plugin-sign keygen [flags]
plugin-sign sign [flags] [plugin.so ...]
plugin-sign verify [flags] [plugin.so ...]
plugin-sign -h
Run plugin-sign <command> -h to see flags for a specific command.
Generate an Ed25519 key pair (recommended):
plugin-sign keygen -alg ed25519 -priv-out private.pem -pub-out public.pemECDSA P-256:
plugin-sign keygen -alg ecdsa -priv-out private.pem -pub-out public.pemRSA-PSS (default 3072 bits, range 2048–4096):
plugin-sign keygen -alg rsa -rsa-bits 3072 -priv-out private.pem -pub-out public.pemBy default keygen refuses to overwrite existing files — pass -force to replace them. The private key is written with mode 0600; the public
key with 0644. Output format: PKCS#8 PEM for the private half, PKIX PEM for the public half — directly consumable by sign/verify.
If you prefer openssl over the built-in generator:
# Ed25519
openssl genpkey -algorithm ed25519 -out private.pem
openssl pkey -in private.pem -pubout -out public.pem
# ECDSA P-256
openssl ecparam -name prime256v1 -genkey -out private.pem
openssl ec -in private.pem -pubout -out public.pem
# RSA-PSS
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out private.pem
openssl rsa -in private.pem -pubout -out public.pemplugin-sign sign accepts PKCS#8, PKCS#1, SEC1 EC, and raw Ed25519-seed private keys, so all of the above work.
Sign specific plugin files:
plugin-sign sign -key private.pem plugin1.so plugin2.soSign all .so files in a directory:
plugin-sign sign -key private.pem -dir ./pluginsVerbose output:
plugin-sign sign -key private.pem -dir ./plugins -vVerify a plugin signature:
plugin-sign verify -pubkey public.pem plugin.soVerify all plugins in a directory:
plugin-sign verify -pubkey public.pem -dir ./plugins-
Keygen: Produces a key pair. Private half is
x509.MarshalPKCS8PrivateKeywrapped in aPRIVATE KEYPEM block; public half isx509.MarshalPKIXPublicKeywrapped in aPUBLIC KEYPEM block. -
Signing: Reads the plugin file, computes SHA-256 hash, signs the hash with the private key, and writes raw signature bytes to a
.sigfile. -
Verification: Reads both the plugin and its
.sigfile, computes the plugin's SHA-256 hash, and verifies the signature matches using the public key. -
File convention: For each
plugin.so, the signature is stored inplugin.so.sigin the same directory.
The signed plugins work with the go-atlas plugin manager:
import (
"github.com/altessa-s/go-atlas/plugins"
)
// Configure manager with public key
mgr := plugins.NewManager(
plugins.WithSignature(plugins.SignatureOptions{
Mode: plugins.SignatureRequire,
PublicKey: publicKeyPEM,
}),
plugins.WithDir("./plugins"),
)
// Load signed plugins
if err := mgr.Load(ctx); err != nil {
// Unsigned or tampered plugins will be rejected
}- name: Sign plugins
run: |
echo "${{ secrets.PLUGIN_SIGN_KEY }}" > private.pem
plugin-sign sign -key private.pem -dir ./plugins
rm private.pem# Sign plugins during build
RUN plugin-sign sign -key /keys/private.pem -dir /app/plugins-
Protect private keys: Never commit private keys to version control.
keygenwrites the private file with0600to start, but storage and transport are your responsibility — use secrets management. -
Key rotation: Periodically rotate signing keys. The plugin manager can be configured with multiple public keys during transition.
-
Algorithm choice: Ed25519 is recommended for its security, performance, and small key/signature sizes.
-
Verification: Always verify signatures in production. Use
SignatureRequireorSignatureEnforcemodes.
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Runtime error (signing/verification failed, key load failed, I/O error) |
2 |
Usage error (unknown command, missing required flags, etc.) |
# 1. Generate keys
plugin-sign keygen -alg ed25519 -priv-out private.pem -pub-out public.pem
# 2. Build plugins
go build -buildmode=plugin -o auth.so ./plugins/auth
go build -buildmode=plugin -o cache.so ./plugins/cache
# 3. Sign plugins
plugin-sign sign -key private.pem auth.so cache.so
# 4. Verify signatures
plugin-sign verify -pubkey public.pem auth.so cache.so
# 5. Deploy
# - Copy plugins and .sig files to production
# - Configure app with public.pemSign all plugins after build:
find ./plugins -name "*.so" -exec plugin-sign sign -key private.pem {} \;Verify all before deployment:
plugin-sign verify -pubkey public.pem -dir ./plugins || exit 1The previous release used a flag-only interface with -verify as a mode toggle. The verb-style CLI is a breaking change — update scripts as
follows:
| Before | After |
|---|---|
plugin-sign -key private.pem plugin.so |
plugin-sign sign -key private.pem plugin.so |
plugin-sign -key private.pem -dir ./plugins |
plugin-sign sign -key private.pem -dir ./plugins |
plugin-sign -verify -pubkey public.pem plugin.so |
plugin-sign verify -pubkey public.pem plugin.so |
openssl genpkey -algorithm ed25519 -out priv.pem (+ openssl pkey -pubout) |
plugin-sign keygen -alg ed25519 -priv-out priv.pem -pub-out pub.pem |