SECURE LINK node://signaling.genebrew.local tls 1.3 / x25519 / aes-gcm-256
build 2026.05.03 SUB-PROJECT 01/06 draft
::: STATUS sub-project #1 implemented, build-verification pending ::: THREAT MODEL Signal-level (option B) — content + partial metadata ::: CRYPTO X3DH · Double Ratchet · Sealed Sender · libsignal-android ::: TRANSPORT WebRTC DataChannel + encrypted store-and-forward ::: STORAGE Room + SQLCipher + Android Keystore ::: DISCOVERY SHA-256 phone hash · 16-bit bucket · OPRF (F-6) ::: NEXT WebRTC peer-connection · FCM data-only push · sealed sender prod
INTERNALPre-release · Not Audited
repo: github/messenger spec: 2026-05-03 module: kotlin-multiplatform-gradle target: android 26+

GENEBREW//MESSENGER

Contact-based peer-to-peer encrypted messenger for Android. Sub-project #1 of 6 in a phased program toward a KakaoTalk-class messenger with a usage-bound Gene token. Built on Signal Protocol primitives — no homegrown crypto.

guest@genebrew:~/messenger$ ./gradlew :server:run --info > Configure project :shared > Configure project :server > Task :server:compileKotlin > Task :server:run [OK] ktor engine bound 0.0.0.0:8080 [OK] h2 / postgres-mode db ready (./build/messenger-db.mv.db) [OK] routes :: identity / prekey / discovery / relay / signaling-ws [WARN] build verification not performed in this session — see notes § guest@genebrew:~/messenger$ cat threat-model.md
Signal · B
Curve25519
X3DH + DR
SQLCipher
PSI-lite v1
26 / API 34
§ 01

Threat Model

option B · signal-level

// Protected

  • +
    Message contents. No intermediary — including the relay server — can read plaintext.
  • +
    Partial metadata. Sealed Sender hides "who-sent-to-whom" from the signaling server.
  • +
    Local store. Device seizure does not yield instant decryption (SQLCipher + Keystore-wrapped key).
  • +
    Forward / post-compromise secrecy. Double Ratchet rotates per-message keys.

// Not Protected

  • Traffic-timing analysis. A network observer at the same ISP can infer when and how often peers communicate.
  • Endpoint compromise. Rooted device or active malware defeats the model.
  • Push-notification metadata. The FCM gateway sees the fact-of-push (payload is empty).
  • Lawful warrant. The signaling server operates under its host jurisdiction's legal authority.
§ 02

System Architecture

hybrid · p2p first · server-relayed fallback
   [ ANDROID :: A ]                                                 [ ANDROID :: B ]
         │                                                                 │
         │ (1) WebSocket / TLS 1.3 — auth · prekey upload · signaling     │
         ├─────────────────────┐                       ┌───────────────────┤
                               ▼                       ▼
                    ┌──────────────────────────────────────────┐
                    │     SIGNALING / DISCOVERY  (Ktor)          │
                    │  · pre-key store         (X3DH bootstrap)│
                    │  · psi-lite discovery    (16-bit bucket) │
                    │  · webrtc sdp / ice relay                │
                    │  · sealed-sender mailbox (offline queue) │
                    │  · fcm trigger           (data-only)     │
                    └──────────────────────────────────────────┘
                               ▲
                               │
         ┌─────────────────────┘  (both online → switch to direct)
         │                                                                 │
         │ (2) WebRTC DataChannel — DTLS-SRTP — Signal layer on top           │
         ◄═════════════════════════════════════════════════════════════════►
         │                                                                 │
         │ (3) FCM data-only — wakes the device, payload is empty {"v":"1"}│
         ◄─────────────────────────────────────────────────────────────────┤

// Direct path (both online)

WebRTC DataChannel over DTLS, with the Signal Protocol envelope inside it. Transport is treated as untrusted. STUN: Google public; TURN: self-hosted coturn for symmetric NAT and carrier mobile networks.

// Relayed path (recipient offline)

Sender uploads sealed envelope to mailbox; server triggers FCM data-only push. Recipient wakes, polls, decrypts on device. ACK clears the queue. Unacknowledged envelopes auto-purge after 30 days; per-user cap is 1000 / 100 MB (whichever is lower).

§ 03

Crypto Stack

no rolled-our-own primitives
P · 01

X3DH

Extended Triple Diffie-Hellman. Bootstraps a fresh session against the recipient's pre-key bundle (signed pre-key + one-time pre-key).

P · 02

Double Ratchet

Per-message symmetric ratchet + DH ratchet. Provides forward secrecy and post-compromise security inside a session.

P · 03

Sealed Sender

Hides the sender identity in the envelope from the signaling server. Production cert (Ed25519) ships in F-5.

P · 04

Identity Key

Long-term Curve25519 keypair. Generated on first launch, stored under Android Keystore. Account ID = b64url(sha256(pub))[0:16].

L · 01

libsignal-android

Audited reference implementation. We wrap it; we do not reimplement primitives.

L · 02

SQLCipher · Keystore

SQLCipher passphrase wrapped by an AES-256 Keystore key. Opaque blob stored in SharedPreferences.

§ 04

Privacy-Preserving Discovery

your contact list never leaves the device in cleartext
   // v1 — bucketed lookup (PSI-lite). Full OPRF ships in F-6.

   1. client extracts E.164-normalized numbers from address book
   2. for each ↦ SHA-256("messenger:" || E164) — keep top 16 bits as bucket
   3. client uploads bucket-set only (NEVER full hashes, NEVER plaintext numbers)
   4. server returns candidate routing-tokens whose bucket overlaps
   5. client runs OPRF check per candidate — exact match, server learns nothing

   // known v1 limitation
   ─ bucket-only matching is not full mathematical PSI;
     plaintext phone numbers still never reach the server.
§ 05

Module Manifest

gradle multi-module · kotlin 2.1 · jdk 17
Module Status Responsibility
:sharedimplementedProtocol DTOs — RegisterAccount, PreKeyBundle, Discovery, Relay, Signaling (kotlinx-serialization)
:serverimplementedKtor app · H2/Postgres-mode DB · Exposed schema · identity / prekey / discovery / relay routes · WebSocket signaling hub · JUnit 5 tests
:android:core:storageimplementedRoom entities + DAOs · SQLCipher · Keystore-wrapped DB key
:android:core:identityimplementedAccount-ID derivation · key lifecycle
:android:core:cryptoimplementedlibsignal wrappers · Room-backed SignalProtocolStore · X3DH / Double-Ratchet roundtrip test
:android:core:discoveryimplementedE.164 normalizer · bucket hasher · lookup HTTP client
:android:core:networkimplementedKtor HTTP / WebSocket clients (identity, prekey, relay, signaling)
:android:core:messagingimplementedMessageSender · MessageReceiver · Outbox · ConversationRepository
:android:appimplementedCompose Material3 nav shell · KakaoTalk-tinted theme

// Deferred — still inside sub-project #1

F-1
Wire ChatList / ChatRoom to ConversationRepository + MessageSender via Hilt ViewModels.UI ↔ messaging facade
F-2
Read device contacts via ContentResolver, normalize, hash, sync to discovery.contact-import path
F-3
WebRTC PeerConnection setup using SignalingClient — switch sender to direct DataChannel when both peers online.p2p hot-path
F-4
FCM data-only push + MessageReceiver.pollAndProcess.wake-up loop
F-5
True sealed sender — server-issued SenderCertificate (Ed25519) + SealedSessionCipher end-to-end.metadata hardening
F-6
Production PSI (OPRF) replacing v1 bucket-only matching.discovery hardening
§ 06

Program Roadmap

option C · commercial-track · 6 sub-projects
SP · 01
CURRENT
P2P Encrypted Core

1:1 text · phone-discovery · E2EE · WebRTC + relay · usable shell

SP · 02
UI / UX Polish

KakaoTalk-grade design pass over the Compose shell

SP · 03
Usage Measurement

Verifiable activity metrics — prerequisite for the token

SP · 04
Gene Token

Ledger · mining algorithm · time-decay · pre-mine

SP · 05
Build Variants

Master vs. regular flavors · staged rollout

SP · 06
Audit + Beta

External security audit · public beta · GA release

§ 07

Honest Notes

read before deploying anywhere near real users

Build verification was not performed in this session. The terminal that authored the code has JDK 17 but no Android SDK and no Gradle CLI. All sources are written against documented APIs but compile / test passes must be run from Android Studio.

Do not deploy this for real users yet. Sealed Sender is currently a placeholder, the discovery PSI is bucket-only (not full PSI), and there has been no external security audit.

Korean legal review — 가상자산이용자보호법 / 특금법 — is required before sub-project #4 (token mining + ledger). This affects corporate structure and runs as a parallel non-code workstream.

§ 08

Build // Run

jdk 17 · android studio ladybug+ · gradle 8.9
# --- server ---------------------------------------- ~/messenger$ ./gradlew :server:run listens on :8080 · H2 file db @ server/build/messenger-db.mv.db override via env: PORT · DATABASE_URL · DATABASE_USER · DATABASE_PASSWORD # --- android app ----------------------------------- ~/messenger$ ./gradlew :android:app:assembleDebug apk → android/app/build/outputs/apk/debug/app-debug.apk # --- jvm unit tests -------------------------------- ~/messenger$ ./gradlew test :shared · :server · :android:core:identity :android:core:discovery · :android:core:crypto [note] repo does not ship gradle-wrapper.jar — open in Android Studio once to materialize the wrapper, or run: gradle wrapper --gradle-version 8.9
§ 09a

Download // Install

Android APK — direct install (not on Play Store yet)

Download Genebrew Messenger

Always points to the latest stable release. Updates after install happen via in-app OTA.

⬇ Download APK (latest)
http://104.238.151.252/d/official
⚠ If you already installed an old version from a different source, uninstall it first (signature mismatch will block update).
Install steps:
  1. Tap the button above to download the APK
  2. Open the downloaded file (allow "install from unknown sources" if prompted)
  3. Tap "Install"
  4. Open the app and follow setup
§ 09

Issues // Vote

bug reports + feature requests — anonymous voting
Loading...