Reference
FAQ
Scope, limits, and where waxseal fits next to the tools you already use.
Questions
Is anything uploaded when I use the demo?
No. The bundled Merkle and inclusion-proof code runs entirely in this tab. It hashes with a vendored JavaScript SHA-256 shim, not node:crypto, and makes no network requests. Reload the page and the state is gone.
Does a valid seal prove who signed it?
No. It proves the signer held the private key matching the embedded public key, and that the archive matches the committed root. There is no identity or trust model for that key. Pin --public-key or --root to turn self-consistency into trust.
Does it prove when the archive was sealed?
No trusted timestamp. createdAt is self-asserted by the signer. Pair the root with a timestamping authority if you need a proven "existed before" time.
What happens if I re-zip the same content?
A member-level check tolerates it, because leaves are (normalized path, content SHA-256) pairs and the root is unchanged. Strict byte mode (archiveSha256) catches any byte difference, including appended trailing bytes that leave every member unchanged.
How do I verify a single file fully offline?
Sealing with --proofs emits one inclusion proof per member, plus the root and each member's content SHA-256. Hand over one proof and run waxseal proof-verify --proofs <proofs.json> --path <member> --root <hex-root> --sha256 <hex-content-hash> — no archive and no network required.
How does waxseal relate to py-wacz?
They are complementary. py-wacz validates the WACZ's own datapackage chain inside the archive; waxseal adds a detached, portable Merkle-and-Ed25519 proof layer on top of the same members.
Why can't the browser demo sign?
Ed25519 key generation, signing, and signature verification require the CLI, which uses local node:crypto. The demo intentionally covers only the Merkle root and inclusion proofs, which run fully client-side.
What happens with a malformed or oversized archive?
It fails safely. Extraction is bounded to 65,535 members and 1 GiB uncompressed, ZIP paths are normalized (Unicode NFC, leading ./ removed, absolute and .. paths rejected), and the CLI reports a structured error instead of crashing.
Limitations
What waxseal does not claim
- ZIP member order and metadata are not part of the sealed bytes; use strict byte mode when you need byte-for-byte attestation.
- Ed25519 only — no X.509 or ECDSA.
- The datapackage digest re-check overlaps py-wacz; waxseal is a portable proof layer on top, not a replacement.
- No identity or trust model for the public key beyond pinning
--public-keyor--root. - No trusted timestamp:
createdAtis self-asserted by the signer.
How it compares
datapackage-digest.json matches datapackage.json and every resource hash and byte count. It is Python, and its check is bound to the ZIP it validates. github.com/webrecorder/py-wacz