# 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` — yields one chunk per `chunkSize - HEADER_SIZE` payload 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 with `CHUNKS.METADATA_INVALID`. - `TAG_LENGTH` constant (16) for the AEAD tag size. - Synchronous generator — no async overhead, allocations bounded per chunk. ## Usage: Basic Example ```ts 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 ```ts 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` — `EncryptOptions` carries `plaintext`, `fileId`, `fileKey`, `baseNonce` (24 bytes), `chunkSize`, `serverPrivKey`. Yields `{ rawBytes, metadata }` per chunk. - `deriveNonce(baseNonce: Uint8Array, chunkId: number): Uint8Array` — XORs `chunkId` into 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.