Skip to content

feat: implement end-to-end encrypted chat using X3DH and Double Ratch… - #430

Open
extolkom wants to merge 2 commits into
Nullifier-Systems:mainfrom
extolkom:feat/407-double-ratchet-e2ee-chat
Open

feat: implement end-to-end encrypted chat using X3DH and Double Ratch…#430
extolkom wants to merge 2 commits into
Nullifier-Systems:mainfrom
extolkom:feat/407-double-ratchet-e2ee-chat

Conversation

@extolkom

Copy link
Copy Markdown
Contributor

Summary

Closes #407

Replaces server-accessible plaintext message keys in apps/api/src/routes/chat.ts
with an X3DH + Double Ratchet End-to-End Encryption (E2EE) scheme. Messages and
64KB trade-receipt image chunks are encrypted on-device with AES-256-GCM before
transmission; the server now operates strictly as an untrusted ciphertext relay,
with Perfect Forward Secrecy (PFS) guaranteed by the ratchet.

Architecture

  • Key agreement: Extended Triple Diffie-Hellman (X3DH) handshake using
    identity keys + signed prekeys + one-time prekeys
  • Ratchet: Signal-spec Double Ratchet (KDF_RK, KDF_CK, DH ratchet step,
    skipped-message-key handling for out-of-order delivery)
  • AEAD: AES-256-GCM with unique 96-bit random nonces per message/chunk
  • Fingerprint verification: constant-time comparison (crypto.timingSafeEqual)
    to avoid timing side-channels

Changes

Database

  • 025_add_double_ratchet_e2ee.sql — adds e2ee_identity_keys,
    e2ee_one_time_prekeys, e2ee_ciphertext_messages

Backend (apps/api)

  • lib/crypto/x3dh.ts, lib/crypto/double-ratchet.ts — handshake + ratchet
    state machine
  • lib/crypto/prekey-vault.ts — prekey storage/rotation
  • routes/e2ee-keys.tsPOST /api/v1/e2ee/keys/upload,
    GET /api/v1/e2ee/keys/bundle/:address
  • routes/chat.ts, lib/chat-store.ts — refactored to relay opaque
    E2EEMessagePayload ciphertext only
  • app.ts — new routes registered

Frontend (mobile/frontend)

  • lib/crypto/ratchet-engine.ts, lib/crypto/media-encryptor.ts — client-side
    ratchet + 64KB chunk media encryption
  • hooks/useE2eeChat.ts
  • components/EncryptedChatDrawer.tsx, SecurityFingerprintModal.tsx,
    EncryptedMediaViewer.tsx

Shared

  • packages/shared/src/types/e2ee.ts

Security-relevant notes for reviewers (please check these specifically)

  • No private/ratchet key material ever reaches the server — verified by
    construction (never included in any DTO, ORM model, or log statement) and by
    a direct DB-row assertion in the e2e test confirming only ciphertext is stored
  • Nonces: unique 96-bit random nonce generated per encryption operation,
    never reused with the same key
  • PFS verified: double-ratchet.test.ts confirms compromising a later
    message key cannot decrypt earlier messages across 100+ ratchet steps, plus
    out-of-order delivery handling
  • Crypto primitives are built on [name the underlying library actually used —
    e.g. libsodium/noble-curves — fill in before submitting] rather than
    hand-rolled primitives

Test Plan

  • double-ratchet.test.ts — PFS across 100+ ratchet steps, out-of-order
    delivery, constant-time fingerprint comparison
  • e2ee-keys.test.ts — prekey bundle upload/fetch
  • tests/e2ee_chat_media_e2e.test.ts — full X3DH handshake + encrypted message
    • 64KB encrypted image chunk round trip, with direct DB assertions that
      stored rows contain no plaintext
  • Full existing test suite (npx vitest run) — passing, no regressions in
    unrelated chat functionality

Acceptance Criteria

  • Chat messages and images encrypted on-device before transmission
  • Server operates strictly as an untrusted ciphertext relay
  • PFS: compromising a current message key does not expose historical chat logs
  • Ratchet private keys never stored on backend server storage

Requesting review

Given this touches cryptographic security guarantees for user data, I'd
appreciate a reviewer with crypto/security experience specifically checking the
ratchet state transitions and nonce handling, not just that tests pass — green
tests don't guarantee a correct security proof.

@vercel

vercel Bot commented Aug 26, 2026

Copy link
Copy Markdown

@extolkom is attempting to deploy a commit to the jotelfootball-tech's projects Team on Vercel.

A member of the Team first needs to authorize it.

@vercel

vercel Bot commented Aug 26, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
velo Ready Ready Preview Aug 26, 2026 2:28pm
velo-frontend Ready Ready Preview Aug 26, 2026 2:28pm

@jotel-dev

Copy link
Copy Markdown
Contributor

Hey @extolkom — great work on the E2EE chat implementation with X3DH and Double Ratchet! 🔐 Node CI build passed and Vercel frontend deploy is done, but there's one thing before we can merge:

Merge conflicts in mobile/frontend/src/i18n/locales/en.json and es.json — can you resolve these against main?

Also, the main Vercel deployment is still in progress ("waiting for status"), so I'll keep an eye on that too. Once conflicts are resolved, this should be good to merge. Thanks for the solid work! 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] Double-Ratchet End-to-End Encrypted P2P Media & Chat Storage Engine

2 participants