2.9 KiB
signature
(no submodules)
Purpose
signature.ts is the Ed25519 signature-verification gate run by the
loader before any packed bytes are handed to Unpacker.unpack. It
exists because the upstream audit (enterprise/packer-browser.md §3.5)
explicitly required archive-signature verification — without it, an
attacker who can substitute the bytes at the packed URL can ship
arbitrary content to the page. By verifying the manifest signature
under a caller-supplied public key first, the loader gives consumers a
hard cryptographic anchor before any decompression / decryption runs.
Features
- Thin wrapper over
@suaveplan/crypto'sed25519.verify— single authoritative implementation, no parallel curve code. - Boundary defence: a signature whose length is not 64 bytes throws
PackerBrowserError(ARCHIVE_SIGNATURE_INVALID)rather than silently returningfalse. This catches wire corruption / header mis-parse before it pollutes downstream logs. - Returns a boolean for cryptographic verify-or-not — never throws on a non-verifying-but-well-formed signature (that's a domain decision the caller makes; the loader throws on the bool side).
- Optional
messageResolverfor i18n on the boundary throw.
Usage: Basic
import { verifyArchiveSignature } from "@suaveplan/packer-browser";
const ok = verifyArchiveSignature(manifestBytes, signature, publicKey);
if (!ok) throw new Error("signature did not verify");
Usage: Advanced
import { ed25519 } from "@suaveplan/crypto";
import { verifyArchiveSignature } from "@suaveplan/packer-browser";
const { publicKey, secretKey } = ed25519.generateKeypair();
const message = new TextEncoder().encode("manifest:v1");
const sig = ed25519.sign(secretKey, message);
const valid = verifyArchiveSignature(message, sig, publicKey);
// valid === true
const tampered = new Uint8Array(sig);
tampered[0] ^= 1;
const invalid = verifyArchiveSignature(message, tampered, publicKey);
// invalid === false
API Reference
verifyArchiveSignature(manifestBytes, signature, publicKey, opts?)— returnsboolean.- Throws
PackerBrowserError(ARCHIVE_SIGNATURE_INVALID)whensignature.length !== 64. - Forwards
publicKeytoed25519.verify, which throws if the key length is not 32 bytes.
- Throws
VerifyArchiveSignatureOptions:messageResolver?: MessageResolver— resolver for the boundary error message.
Implementation Notes
Signature material is conventionally hex-encoded in the
X-Archive-Signature response header; the loader decodes it before
calling this function. The public key is not sourced from the wire
— the loader requires the caller to pass verifyKey on
PackedResourceLoadOptions, ensuring an out-of-band trust anchor.
Cluster B's encrypted-archive keyring adds the per-key public-key
selection step on top of this primitive; Cluster A simply takes one
public key per load(...) call.