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).
39 lines
1.3 KiB
TypeScript
39 lines
1.3 KiB
TypeScript
/**
|
|
* Tests for `crypto.init()`.
|
|
*
|
|
* libsodium ships as WebAssembly. The bindings (`libsodium-wrappers-sumo`)
|
|
* load asynchronously: the runtime must `await sodium.ready` once before any
|
|
* crypto call is safe. quack hides that detail behind a single
|
|
* `init()` function.
|
|
*
|
|
* Every other test in `test/crypto/**` calls `init()` in `beforeAll`. New
|
|
* code that needs crypto should do the same. Calling it more than once is
|
|
* cheap and intentional; the second call returns the same already-resolved
|
|
* promise.
|
|
*/
|
|
|
|
import { beforeAll, describe, expect, it } from "vitest";
|
|
import { init } from "../../src/crypto/index.js";
|
|
|
|
describe("crypto.init", () => {
|
|
beforeAll(async () => {
|
|
await init();
|
|
});
|
|
|
|
it("resolves without throwing", async () => {
|
|
// The success criterion is simply that the promise resolves. If
|
|
// libsodium's WASM fails to load, `init()` rejects and this test
|
|
// fails.
|
|
await expect(init()).resolves.toBeUndefined();
|
|
});
|
|
|
|
it("is idempotent: repeated calls are safe", async () => {
|
|
// Code paths in this library may call `init()` defensively (e.g. a
|
|
// `Client` constructor that doesn't know whether the caller already
|
|
// initialised). Repeated calls must therefore be harmless.
|
|
await init();
|
|
await init();
|
|
await init();
|
|
});
|
|
});
|