2.4 KiB
build
Purpose
Constructs a server-signed Manifest for an ingested file: bundles the file metadata (fileId, fileSize, chunkSize, totalChunks), encryption envelope (algo, fileKeyWrapped, baseNonce), and per-chunk integrity hashes into a single record, then signs the canonical encoding under the server private key. The manifest is the consensus artefact: peers that trust the server public key can verify it without holding any chunk bytes.
Features
buildManifest(options): Manifest— pure function, no I/O, no global state.canonicalSerialize(manifest): Uint8Array— deterministic big-endian length-prefixed encoding suitable for cross-platform Ed25519 signing.algois encoded as a length-prefixed UTF-8 string so future encryption algorithms can be added without breaking the wire format.- Per-chunk entries pack
(chunkId: u32, hash: 32 bytes, payloadLen: u32)into 40 bytes — bounded growth, predictable memory.
Usage: Basic Example
import { buildManifest } from "@suaveplan/drive-plugin-chunks";
const manifest = buildManifest({
fileId: sha256Bytes,
fileSize: 12n,
chunkSize: 1024,
totalChunks: 1,
encryption: { algo: "xchacha20poly1305", fileKeyWrapped: fileKey, baseNonce },
chunks: [{ chunkId: 0, hash: chunkHash, payloadLen: 12 }],
serverPrivKey,
});
Usage: Advanced Example
import { buildManifest, canonicalSerialize } from "@suaveplan/drive-plugin-chunks";
import { verify } from "@suaveplan/crypto-curve/ed25519";
const manifest = buildManifest({ /* ... */ });
const { sig, ...base } = manifest;
const ok = verify(sig, canonicalSerialize(base), serverPubKey);
API Reference
buildManifest(options): Manifest— returns{ version, fileId, fileSize, chunkSize, totalChunks, encryption, chunks, sig }.canonicalSerialize(manifest: Omit<Manifest, "sig">): Uint8Array— used both for signing and for verification.
Implementation Notes
Field order in canonicalSerialize is fixed and big-endian; changing it would break every previously-stored manifest. The algo length prefix makes the encoded form self-delimiting so receivers don't need an explicit version bump to add new algorithms — they only need to add a parsing branch keyed on the algo string. The final buf.slice(0, off) trims any over-allocated tail, but totalLen is computed exactly so this is normally a no-op.