first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
# 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 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<EncodedChunk>` — `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.