Reference
The commands
Five commands cover the whole lifecycle: make a key, seal an archive, verify it later, prove a single member, and inspect the archive's own datapackage chain. Signing and verification run locally against node:crypto.
Commands and options
| Command | What it does |
|---|---|
waxseal keygen [--out <base>] [--force] |
Generate an Ed25519 key pair (default base waxseal-key) → <base>.pem (private, PKCS#8) and <base>.pub.pem (public, SPKI). Refuses to overwrite unless --force/--yes. |
waxseal seal <archive.wacz> [--key <pem>] [--out <seal.json>] [--proofs <proofs.json>] [--json] |
Create a detached seal for an archive. With no --key, a new key pair is generated and written next to the archive, with a warning. |
waxseal verify <archive.wacz> -s <seal.json> [--public-key <pem|base64>] [--root <hex>] [--json] [--member-only] |
Verify an archive against a seal. Strict byte-level by default; --member-only allows a re-zip. The SPKI key fingerprint is always printed. Pass --public-key or --root to pin a trusted key or root; without one the seal is only self-consistent and is labelled trusted: no. |
waxseal proof-verify [<archive.wacz>] --proofs <proofs.json> [--seal <seal.json>] [--path <member>] [--root <hex>] [--sha256 <hex>] [--json] |
Verify Merkle inclusion proofs. With an archive, proofs are checked against its rebuilt root (or --seal/--root). Without an archive, pass --root or --seal plus the member's --sha256 for a fully offline check. Omit --path to check every proof in the file. |
waxseal inspect <archive.wacz> [--json] |
Inspect members, datapackage digest status, and the Merkle root. |
Run waxseal --help for the full list of options, or waxseal --version for the installed version.
Sealing an archive
seal builds the Merkle root over the archive members and signs a canonical payload with the key. With --proofs it also emits one inclusion proof per member; with --created-at the seal is reproducible byte for byte.
$ waxseal seal capture.wacz --key archive-key.pem --out capture.seal.jsonarchive: /tmp/opencode/demo.waczseal: /tmp/opencode/refs/demo.seal.jsonroot: 7ce7902d6dc6619e28496d7c717bacfbfb36bc7982b6d424d8d1f11c9218fcf7memberCount: 2algorithm: ed25519signature: 3D0VHjqpApz6TIVAmhlO/R6s...
Verifying a seal
verify rebuilds the root from the archive, checks the Ed25519 signature, and reports whether the seal is trusted. Strict byte-level is the default; --member-only tolerates a legitimate re-zip.
$ waxseal verify capture.wacz -s capture.seal.json --public-key archive-key.pub.pemOKroot: 7ce7902d6dc6619e28496d7c717bacfbfb36bc7982b6d424d8d1f11c9218fcf7signature: validfingerprint: sha256:8b3e7cbe526fdb46b70f4f3a8b2a3992475febd3f02f94a27a3b9395b2d3825ctrusted: no — self-signed seal; pin it with --public-key or --root
Verifying an inclusion proof
proof-verify checks a member against the signed root. With an archive it rebuilds the root and rejects a tampered member; without one, pass --root or --seal plus the member's --sha256 for a fully offline check. Omit --path to check every proof in the file.
Inspecting an archive
inspect reports the members, the datapackage digest status, and the Merkle root without touching a key.
$ waxseal inspect capture.waczarchive: /tmp/opencode/demo.waczdatapackage digest: FAILEDmember count: 2resource count: 0merkle root: 7ce7902d6dc6619e28496d7c717bacfbfb36bc7982b6d424d8d1f11c9218fcf7issue: missing datapackage.json
The trust model
A seal always proves two things on its own: that the archive matches the committed Merkle root, and that the signer held the private key for the public key embedded in the seal. Because the seal carries its own key, that is only self-consistency — it does not make the signer trustworthy. To trust a seal you must pin --public-key <pem|base64> or the expected --root <hex> out of band; the SPKI fingerprint that verify always prints is the value to compare.