Marketplace plugins are signed so the app can prove a package has not been tampered with before it runs. Spirefy uses ML-DSA-65, the post-quantum signature scheme standardized by NIST as FIPS 204, rather than Ed25519, because plugin signatures need a multi-year shelf life.
Generate a key
spirefy key-gen --label my-key
Keys live in your local keystore (~/.config/zora/keys). A key’s fingerprint is the SHA-256 of its public key, written as 64 hex characters, and that fingerprint is how the marketplace and your local store identify it. Add --register to publish the public key once you have a marketplace account.
Sign while packing
Signing happens as part of packaging:
spirefy pack --sign --key my-key
The signature covers the manifest, the WebAssembly, and the WIT, hashed together with length prefixes so the boundaries between them cannot be confused. It is stored inside the .zp package.
Verify
spirefy verify my-plugin-1.0.0.zp --strict --key my-key
spirefy verify checks a package locally. Without --strict, an unsigned plugin warns but passes, while an invalid signature always fails. With --strict, the package must carry a valid ML-DSA-65 signature from a key you trust. Verification happens before the WebAssembly is decompressed, so a tampered package never runs, and the command exits non-zero on failure so it fits in CI.
At load time
When the app loads a plugin it logs the file’s SHA-256 hash, and on POSIX it refuses to load a world-writable plugin file. A marketplace plugin’s signature is checked before it runs.