Phase 2 red: crypto primitive tests and stub modules

Tests for the entire crypto/ public surface, written against the API
shape declared in the README. The accompanying src/crypto/ modules are
stubs that throw 'not implemented' so the test files compile and tests
fail with clear errors rather than module-not-found.

Tests cover:
  * init() resolves and is idempotent
  * fromBase64 / toBase64 / toBase64URL round-trips, including URL-safe
    input with stripped padding (the form Ente uses for auth tokens)
  * deriveKEK matches sodium.crypto_pwhash with Argon2id parameters
  * deriveLoginSubkey matches sodium.crypto_kdf_derive_from_key with
    subkey id 1 and ctx 'loginctx', truncated to 16 bytes
  * decryptBox round-trips, rejects tampering, wrong key, wrong nonce
  * decryptSealed round-trips, rejects wrong keypair and tampering
  * Secretstream pull decrypts multi-chunk streams in order, exposes
    per-chunk tags, rejects tampering, wrong key, and out-of-order chunks
  * Constants STREAM_CHUNK_SIZE (4 MiB) and STREAM_CHUNK_OVERHEAD (17)

Tests are commented to serve as the canonical API documentation per the
README development workflow policy. Verified: 29 tests fail (red), 3
trivial constant tests pass; lint and fmt-check are green.

eslint.config.mjs is updated to honour the leading-underscore convention
for intentionally unused parameters (the stubs).
This commit is contained in:
2026-05-09 12:43:52 -07:00
parent 64a3ace33a
commit 676d42c5eb
12 changed files with 695 additions and 0 deletions

22
src/crypto/stream.ts Normal file
View File

@@ -0,0 +1,22 @@
// Stub: see the README "Development workflow" section for TDD policy.
export const STREAM_CHUNK_SIZE = 4 * 1024 * 1024;
export const STREAM_CHUNK_OVERHEAD = 17;
export interface StreamPullState {
readonly _opaque: unique symbol;
}
export const initStreamPull = (
_header: Uint8Array,
_key: Uint8Array,
): StreamPullState => {
throw new Error("crypto.initStreamPull not implemented");
};
export const pullStreamChunk = (
_state: StreamPullState,
_ciphertext: Uint8Array,
): { plaintext: Uint8Array; tag: number } => {
throw new Error("crypto.pullStreamChunk not implemented");
};