Some checks failed
Test / test (push) Has been cancelled
Cross-platform vectors / TypeScript vectors (bun) (push) Has been cancelled
Cross-platform vectors / Kotlin vectors (gradle) (push) Has been cancelled
Docker build and publish / docker (push) Has been cancelled
Publish / publish (push) Has been cancelled
V3.1 → V3.12 consolidated and tagged for the first GA release. Wire format unchanged from 0.4.x — 4.0 peers interoperate with 0.4.x peers byte-for-byte. The version bump is semantic: audit-cycle complete, opt-in surface fully exposed, threat model refreshed for every new surface. Highlights: - All 24 @shade/* packages bumped to 4.0.0 in lockstep. - CHANGELOG 4.0.0 section is the canonical manifest of what landed. - THREAT-MODEL extended (§10 fingerprint gates, §11 WebRTC P2P, §12 Web-Worker boundary) + residual-risks table refreshed. - OpenAPI now covers all 27 routes: prekey, transfer, KT, inbox, bridge, observer, /metrics, /healthz, /ready. - MIGRATION 0.3.x → 4.0 documented + smoke-tested against shade migrate-storage on a real SQLite DB. - docs/audit/REVIEW-BUNDLE.md + SCOPE.md ready for external reviewer. - scripts/soak.ts harness for the GA-stable 2-week soak window. - All V*.md plans archived under docs/archive/ with Status: Done. - Voice/Video carved out into V5.0; 4.0 audit focuses on the frozen non-realtime stack. Tests: TS 1000/1000 + Kotlin 11/11 cross-platform vectors green. Docker: gt.zyon.no/stian/shade-prekey:4.0.0 builds and reports version 4.0.0 on /health. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3.6 KiB
3.6 KiB
Shade 4.0 — Audit Scope
A short, structural list a reviewer can scan before opening a single
file. Everything here is a pointer to the deeper material in
REVIEW-BUNDLE.md and the package READMEs.
In scope
- Protocol primitives: X3DH, Double Ratchet, sender keys.
- Wire format:
0x01PreKeyMessage,0x02RatchetMessage,0x11StreamChunk. Length prefixes (u32) and AAD bindings. - Storage encryption (
@shade/storage-encrypted): KDF chain, per-(table,column) DEKs, AEAD AAD layout, online re-key. - Recovery (
@shade/recovery): Shamir over GF(2^8), AEAD-authenticated reconstruction, fingerprint gate on guardian release, share-grant / share-decline envelope schema. - WebRTC P2P (
@shade/transport-webrtc): SDP/ICE signaling rides the ratchet; chunk frames AEAD-bound to streamId/laneId/seq; glare resolution determinism. - Key Transparency (
@shade/key-transparency): Merkle log over pre-hashed leaves, address-sorted index, signed STH, witness cross-check, split-view detection. - Inbox (
@shade/inbox-server): TOFU registration, per-PUT signed blobs, idempotent on(address, msgId), replay window. - Bridge (
@shade/transport-bridge): SSE / long-poll / WS carriers; signed-query auth (no headers onEventSource). - Crypto in workers (
@shade/crypto-web/worker): key-isolation boundary, postMessage protocol, idle terminate. - Trust UX gates (
@shade/sdkShade.beforeFirstLargeFile,beforeBackupImport,beforeNewDeviceTrust).
Out of scope
- Voice / Video / Broadcast (
@shade/voiceetc.) — V5.0; reviewed when the package ships. - Build system (Vite, Rollup, Gradle wiring) — out of crypto scope.
- App-level UI (
@shade/widgets) — re-renders the primitives above; the cryptographic decisions are in the SDK / core packages the widgets consume. - Browser / native WebRTC stacks — we ride the platform's
RTCPeerConnectionandSubtleCrypto. - Operating system / hardware threat model — filesystem encryption, secure-enclave key storage, swap-encryption, coredump handling. Operator responsibility.
Methodology suggestions
- Start with
THREAT-MODEL.md— every entry has a[tests:]footnote. Toggle each test off, confirm it fails; toggle the corresponding mitigation off, confirm it fails. - Re-derive every KDF label from the spec; check
scripts/generate-vectors.tsand the recorded vectors intest-vectors/match. - Run the cross-platform suite on both TS (bun) and Kotlin (gradle) — divergence is a vector-format bug.
- Audit the AEAD AAD construction at every layer:
- Ratchet: header bytes (counter + DH pub) → AES-GCM AAD.
- Streams:
streamId || laneId || seq || isLast→ AES-GCM AAD. - Storage:
(table, column, pk)→ AES-GCM AAD.
- Trace the boundary between the worker-side crypto thread and the main thread — confirm that no handle to a wrapped DEK or a ratcheted chain key crosses over.
Open questions for reviewer commentary
- The witness gossip channel for V3.12 is currently in-band over the ratchet; should we cross-pin against an out-of-band log mirror in 4.x, or wait for a federated relay tier?
- WebRTC peer-glare is resolved by lexicographic address compare — a reviewer could confirm the equivalent constructions in libsignal or Matrix and flag if our edge cases match.
- Storage encryption uses AES-GCM with a per-row IV. The IV is random, not deterministic; reviewers should confirm the combinatorial-collision threshold matches the per-column row count bounds.