2.6 KiB
sign-chunk
Purpose
Signs a chunk under the server's Ed25519 private key. Signatures cover the full encoded chunk (metadata header bytes plus the encrypted payload) so receivers can verify integrity without first decrypting. The output is fixed at 64 bytes, which is the slot reserved by header.ts (SIG_SIZE = 64).
Features
signChunk(chunk, privKey): Uint8Array— produces a deterministic Ed25519 signature overmetadata || ciphertext.buildSignedChunk(chunk, privKey): Chunk— convenience wrapper that returns a chunk with the freshly-computed signature inlined.- Pure function — no global state, no side effects, deterministic for fixed inputs (Ed25519 with seeded keys).
Usage: Basic Example
import { randomPrivateKey } from "@suaveplan/crypto-curve/ed25519";
import { signChunk } from "@suaveplan/drive-plugin-chunks";
const privKey = randomPrivateKey();
const chunk = {
metadata: { /* ChunkMetadata */ } as never,
sig: new Uint8Array(64),
ciphertext: new Uint8Array([1, 2, 3]),
};
const sig = signChunk(chunk, privKey);
Usage: Advanced Example
import {
buildSignedChunk,
parseChunk,
verifyChunkSig,
} from "@suaveplan/drive-plugin-chunks";
const signed = buildSignedChunk(parseChunk(rawChunk), serverPriv);
verifyChunkSig(/* raw bytes containing signed.sig */, serverPub);
API Reference
signChunk(chunk: Chunk, privKey: Uint8Array): Uint8Array— returns 64-byte signature. ConcatenatesencodeHeader(metadata)andchunk.ciphertextthen signs the concatenation.buildSignedChunk(chunk: Chunk, privKey: Uint8Array): Chunk— same chunk with a populatedsigfield.
Implementation Notes
The signature input deliberately excludes the existing chunk.sig field — re-signing a chunk produces the same signature for fixed inputs even though Ed25519 is not strictly deterministic across implementations (suaveplan pins to @noble/curves which is RFC-8032 deterministic). Verification is implemented in verify-chunk.ts using the matching getPublicKey derivation.
The signed payload is encodeHeader(metadata) || ciphertext rather than the full raw chunk because the signature occupies a fixed slot inside the raw bytes; including it in the signing input would be circular. This split also lets transports verify a chunk in two passes: parse the metadata to learn payloadLen, then sign-verify a contiguous range of the buffer without copying. Signing happens at ingest time and is the only place the serverPrivKey ever leaves the plugin's option object — verification only needs the public key.