2.7 KiB
encrypt-stream
Purpose
The encryption pipeline that transforms a plaintext file into a stream of signed encrypted chunks ready for persistence. It owns the chunk-level nonce derivation, the AEAD ciphertext + tag split, the per-chunk metadata population, and the immediate signing pass. Together these steps form the deterministic transform from { plaintext, fileId, fileKey, baseNonce, chunkSize, serverPrivKey } to a stream of EncodedChunk objects.
Features
encryptChunks(options): Generator<EncodedChunk>— yields one chunk perchunkSize - HEADER_SIZEpayload window, signed and ready to persist.deriveNonce(baseNonce, chunkId): Uint8Array— XORs the chunk index into the high-order bytes of the 24-byte XChaCha20 nonce; rejects non-24-byte inputs withCHUNKS.METADATA_INVALID.TAG_LENGTHconstant (16) for the AEAD tag size.- Synchronous generator — no async overhead, allocations bounded per chunk.
Usage: Basic Example
import { randomPrivateKey } from "@suaveplan/crypto-curve/ed25519";
import { encryptChunks } from "@suaveplan/drive-plugin-chunks";
const chunks = Array.from(
encryptChunks({
plaintext: new TextEncoder().encode("hello"),
fileId: new Uint8Array(32),
fileKey: new Uint8Array(32).fill(7),
baseNonce: new Uint8Array(24).fill(11),
chunkSize: 1024,
serverPrivKey: randomPrivateKey(),
})
);
Usage: Advanced Example
import { deriveNonce, encryptChunks, TAG_LENGTH } from "@suaveplan/drive-plugin-chunks";
for (const chunk of encryptChunks({ plaintext, fileId, fileKey, baseNonce, chunkSize: 4096, serverPrivKey })) {
await storage.set(`chunks:${idHex}:${chunk.metadata.chunkId}`, chunk.rawBytes);
}
// Reconstruct the per-chunk nonce on the receiver
const nonce = deriveNonce(baseNonce, chunkIdReceived);
console.log(TAG_LENGTH); // 16
API Reference
encryptChunks(options: EncryptOptions): Generator<EncodedChunk>—EncryptOptionscarriesplaintext,fileId,fileKey,baseNonce(24 bytes),chunkSize,serverPrivKey. Yields{ rawBytes, metadata }per chunk.deriveNonce(baseNonce: Uint8Array, chunkId: number): Uint8Array— XORschunkIdinto bytes 0–3.TAG_LENGTH: 16— AEAD tag size.
Implementation Notes
encryptChunks writes the signature into the raw buffer at [METADATA_SIZE, HEADER_SIZE) immediately after computing it, so consumers can stream chunks through transports without ever holding a full file plaintext in memory. The XOR-based nonce derivation is sound for chunk indices ≤ 2³² because XChaCha20-Poly1305 takes a 24-byte nonce: under fixed baseNonce no two chunks of the same file ever share a nonce.