Cipher (@ap/crypto)

Shared encryption library for Aloysius Productions. Extracts and consolidates cryptographic primitives from haven and Correspondence Chess Pro into a single reusable npm package. Covers Signal Protocol E2E messaging, AES-256-GCM symmetric encryption, and BIP-39 mnemonic passphrases.

Zone: staging (evaluation) Version: v0.1.0 Package name: @ap/crypto


Overview

Cipher is extracted as a copy — not a move — from the Haven and CCP source apps, both of which remain intact and independent. The goal is a single shared dependency consumable by downstream apps: Meridian, Meridian, the unified chess project, and future Scribe integration.


Tech Stack

TechnologyVersionPurpose
TypeScript^5.6.0Language (strict mode)
Vitest^4.0.18Test runner
ESLint^9.39.2Linting (flat config)
tweetnacl^1.0.3Ed25519, Curve25519, XSalsa20-Poly1305
tweetnacl-util^0.15.1Base64/UTF-8 encoding
@privacyresearch/libsignal-protocol-typescript^0.0.16Signal Protocol Double Ratchet
bip39^3.1.0BIP-39 mnemonic generation/validation
idb^8.0.0IndexedDB wrapper (optional — WebKeyStorage)
expo-secure-store>=14.0.0Mobile key storage (optional peer dep)

Build: npm run build (tsc). Tests: npm run test (vitest run).


Key Decisions

DecisionRationale
Extract as copy, not moveGoverning principle — Haven and CCP continue independently
Signal Protocol + AES-256-GCMSignal for E2E messaging; AES-256 for symmetric use cases (game state, settings)
PBKDF2 at 150k iterations (symmetric) / 100k (settings)Symmetric exceeds OWASP 2023 minimum (120k); settings acceptable with additional auth layers
BIP-39 over custom wordlistCCP had a 26-word list (~18 bits entropy); BIP-39 gives 128+ bits with standard tooling
Vitest over JestEcosystem standardized on Vitest across AP (Aura, CCP, Eliza all use it)

Reusable Patterns

Three interfaces extracted from Cipher are documented as standalone patterns in the vault:

  • encryptedpayload-type — Standard shape for passphrase-encrypted data: salt + iv + data + version tag
  • CryptoBackend interface — Swappable crypto primitives; TweetNaCl default, extensible to WebCrypto
  • KeyStorage interface — Platform-agnostic key persistence: Web (IndexedDB), Mobile (SecureStore), Memory (test)

See also: cryptographic-key-exchange for Signal Protocol X3DH context.


Current Status

Phase: Active Development Tests: 143 passing (as of 2026-02-16) CI/CD: security.yml configured, CI not yet run (flaky)

Completed

  • Initial extraction from Haven + CCP (2026-02-06)
  • Comprehensive audit — 113 tests, security fixes applied (2026-02-15)
  • ESLint flat config, constant-time comparison, Haven→Cipher rebranding (2026-02-16)
  • Phase 2 tests: X3DH round-trip, forward secrecy, bidirectional session encryption (2026-02-16)

Remaining

  • Import path standardization — add .js extensions for pure ESM compliance (deferred; bundler resolution works)
  • Publish for consumption by downstream apps (Meridian, chess merge)
  • X3DH respondX3DH shared secret round-trip test (open)
  • Storage module excluded from build due to browser-only APIs (low priority)

Technical Debt

ItemPriorityStatus
X3DH respondX3DH shared secret untestedHighOpen
Storage module excluded from buildLowOpen
ESLint non-null assertions in storage (20 warnings)LowOpen
Import path inconsistency (.js extensions)LowDeferred

Integration Points

ConsumerStatus
MeridianPlanned
Chess (unified)Planned
ScribeQueued
cards-and-gamesQueued