96a8c210b2
feat(hardening): M-Hard 1-5 — crypto, auth, rate limit, fingerprints, rotation
...
M-Hard 1: Cryptographic Hardening
- constantTimeEqual, zeroize, randomUint32 on CryptoProvider
- Fix Math.random() → crypto.randomUint32() for registrationId
- Zero message keys and chain keys after use in ratchet.ts
- Constant-time trust comparison in MemoryStorage + SQLiteStorage
- Timing variance test catches early-exit regressions
M-Hard 2: Self-Authenticated Prekey Server
- Ed25519 signature verification on all write routes
- signPayload/verifyPayload with canonical JSON, ±5 min replay window
- Address validation (NFKC, alphanumeric + :_-.)
- Global ShadeError → HTTP status mapping
- ShadeFetchTransport signs requests when signingPrivateKey provided
- Anonymous bundle fetches still allowed (read-only)
M-Hard 3: Rate Limiting + DoS Protection
- Token bucket rate limiter with pluggable store
- Per-route limits: register 5/h/IP, fetch 60/min/IP, replenish 10/min/id
- 64KB body size limit on POST
- Retry-After header on 429 responses
M-Hard 4: Auto-replenish + Fingerprints + Session Reset
- Safety numbers (12 groups × 5 digits, Signal-style)
- ensurePreKeyStock, resetSession, acceptIdentityChange
- verifyRemoteIdentity for out-of-band comparison
M-Hard 5: Identity Rotation with Grace Period
- rotateIdentity archives old identity, generates fresh signed prekey
- RetiredIdentity storage with addRetired/getRetired/pruneRetired
- 7-day default grace period for decrypting old sessions
- pruneExpiredIdentities for cleanup
M-Hard 8: Error Hierarchy
- New error types: Network, Storage, Validation, Timeout, RateLimit,
Configuration, Unauthorized, Replay, IdentityRotation
- All errors have stable SHADE_* codes
- errorToHttpStatus for consistent HTTP mapping
- toJSON() for network serialization
188 tests passing, zero failures.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-04-10 17:45:34 +02:00
7d214dc614
feat: persistent storage — SQLite backends for crash resilience
...
Shade sessions and keys now survive server crashes, container restarts,
and power outages via SQLite with WAL mode.
New packages:
- @shade/storage-sqlite: SQLiteStorage (StorageProvider) + SqlitePrekeyStore
(PrekeyStore), both using bun:sqlite with auto-created tables and WAL mode
- Serialization layer in shade-core for SessionState/keys ↔ JSON/base64
Docker usage: mount volume at /data, set SHADE_DB_PATH=/data/shade-client.db
Prekey server auto-detects SHADE_PREKEY_DB_PATH for SQLite persistence
Includes crash recovery integration test: encrypt → close DB → reopen →
conversation continues seamlessly.
129 tests, 0 failures.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-04-10 00:19:54 +02:00
d071551b2f
feat: M6 Transport wrappers — fetch + WebSocket adapters
...
- ShadeFetchTransport: HTTP client for prekey server
(register, fetchBundle, replenish, getKeyCount)
- ShadeWebSocket: wraps existing WebSocket with auto E2EE
(binary wire format, transparent encrypt/decrypt)
- Full integration test: register → fetch → session → encrypt → decrypt
over real HTTP against in-process Hono prekey server
101 tests, 0 failures across all milestones (M1-M7).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-04-09 20:18:21 +02:00
740a652d51
feat: M5 Prekey Server + M7 Wire Format
...
M5: Shade Prekey Server (Hono)
- REST API: register, fetch bundle, replenish, count, delete
- MemoryPrekeyStore for testing/embedded use
- Standalone Docker deployment (Dockerfile + standalone.ts)
- One-time prekey consumption on bundle fetch
M7: Compact binary wire format
- Version-tagged envelopes (PreKeyMessage, RatchetMessage)
- Length-prefixed byte arrays, big-endian integers
- Significantly smaller than JSON (no base64 bloat)
- Roundtrip encode/decode for all message types
100 tests, 0 failures across M1-M5+M7.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-04-09 20:16:41 +02:00
bd6452044f
feat: Shade E2EE library — M1-M3 complete
...
Signal Protocol implementation with full X3DH + Double Ratchet:
- M1: Core types, CryptoProvider interface, KDF chain functions,
SubtleCrypto+noble/curves provider, MemoryStorage
- M2: X3DH key agreement (identity keys, signed prekeys, one-time
prekeys, bundle processing for both initiator and responder)
- M3: Double Ratchet (symmetric-key ratchet, DH ratchet, skipped
message key cache, out-of-order delivery, AAD-bound headers)
68 tests, 0 failures — including full integration test of
X3DH handshake → Double Ratchet conversation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-04-09 20:08:19 +02:00