Skip to content

TheFruggg/Ember-5.0

Repository files navigation

Ember Logo

Ember

Decentralized. Encrypted. Ephemeral.

A serverless, peer-to-peer encrypted messaging app for Android — built on Yggdrasil mesh networking and the Double Ratchet protocol.

Android Kotlin Encryption Network License


What is Ember?

Ember is an Android messaging application with no servers, no accounts, and no metadata. Messages travel directly between devices over the Yggdrasil mesh network, encrypted end-to-end using the Double Ratchet algorithm — the same cryptographic protocol that powers Signal.

Every message is encrypted before it leaves your device. No central authority can read, store, or intercept your conversations.


Core Features

Security & Encryption

  • Double Ratchet Protocol — P-256 ECDH key agreement with HKDF-SHA256 key derivation. Every single message is encrypted with a unique key, derived fresh via symmetric and DH ratcheting
  • AES-256-GCM — Authenticated encryption with 256-bit keys, 12-byte random nonces, and 16-byte authentication tags
  • Perfect Forward Secrecy — Compromise of current keys reveals nothing about past messages
  • Future Secrecy — Regular DH ratchet steps mean key compromise heals automatically
  • Encrypted at Rest — SQLCipher encrypts the entire local database; EncryptedSharedPreferences (backed by Android Keystore) protects identity keys and settings
  • Biometric Lock — Optional fingerprint authentication on app resume
  • Screen Security — Optional FLAG_SECURE prevents screenshots and screen recording

Networking

  • Yggdrasil P2P — Pure peer-to-peer over IPv6 mesh networking. No central relay, no STUN servers, no infrastructure to subpoena
  • Direct TCP — Messages sent over raw TCP sockets with buffered I/O (Okio)
  • Automatic Retry — Exponential backoff up to 5 attempts when peers are temporarily unreachable
  • Foreground Service — Continuous background listener so messages are never missed
  • Connection Pooling — Active peer connections reused when possible

Messaging

  • Ephemeral Messages (TTL) — Every message can have a time-to-live: 5 min, 10 min, 30 min, 1 hour, or 1 day. Expired messages are purged automatically by WorkManager
  • Delivery Status — Sent (✓), Delivered (✓✓), and Read (✓✓ highlighted) indicators
  • No Message Previews — Conversation list never exposes message content
  • Real-Time Receive — Messages appear instantly when app is open

Contact Exchange

  • QR Code Pairing — Scan a contact's QR to exchange display name, Yggdrasil address, port, and identity public key in one step
  • Manual Fallback — Hex key entry for air-gapped or CLI scenarios
  • Contact Verification — Mark contacts as verified after out-of-band fingerprint comparison
  • Zero Discovery — No contact syncing, no phone number lookup, no directory

Cryptographic Architecture

Identity Layer
└─ P-256 ECDH key pair (generated once, stored in EncryptedSharedPreferences)
   └─ Public key shared via QR code on contact exchange

Session Initialization
├─ Alice (initiator) — initAlice()
│  ├─ Generates ephemeral DH key pair
│  ├─ ECDH(ephemeral_private, contact_identity_public)
│  └─ Derives (RootKey, ChainKey_send) via HKDF-SHA256
│
└─ Bob (recipient) — initBob()
   ├─ ECDH(identity_private, alice_ephemeral_public) → (RK₁, ChainKey_recv)
   ├─ Generates own ephemeral DH pair
   ├─ ECDH(ephemeral_private, alice_ephemeral_public) → (RK₂, ChainKey_send)
   └─ Full ratchet state established

Per-Message Encryption
├─ Symmetric ratchet: HMAC-SHA256 advances chain key, derives message key
├─ DH ratchet: triggered on each new ephemeral key from sender
├─ Message key used once for AES-256-GCM, then discarded
└─ Skipped message keys cached (up to 100) for out-of-order delivery

Wire Format (EmberEnvelope)
└─ JSON over TCP
   ├─ version, conversationId, sender, timestamp, ttlSeconds
   ├─ ciphertext (Base64), nonce (Base64)
   └─ ratchetHeader: { dhPublicKey (hex), pn, n }

Tech Stack

Layer Technology
Language Kotlin (100%)
UI Jetpack Compose + Material 3
Architecture MVVM + Repository + Hilt DI
Async Kotlin Coroutines + Flow
Database Room + SQLCipher
Preferences EncryptedSharedPreferences
Networking Raw TCP sockets + Okio
Serialization kotlinx.serialization
Crypto Java Security (P-256 EC) + javax.crypto (AES-GCM)
Background WorkManager (TTL cleanup) + Foreground Service
QR Codes ZXing Android Embedded
Min SDK API 26 (Android 8.0)
Target SDK API 35 (Android 15)

Screens

Onboarding

First-launch setup: enter a display name, detect your Yggdrasil IPv6 address, and configure the listening port. Your P-256 identity key pair is generated and persisted here.

Home — Chats

Conversation list with contact avatars, names, and relative timestamps. No message content is ever shown in previews.

Home — Contacts

Full contact list with verification badges. Tap any contact to view their details, fingerprint, and QR code, or start a conversation.

Home — Settings

Edit your display name, Yggdrasil address, and port. Toggle biometric lock and screen security. View version and encryption details.

Chat

Full conversation view with gradient sent-bubbles (orange → red) and dark received-bubbles. TTL chip selector, a gradient send button, and real-time delivery status icons.

Add Contact

Enter contact details manually or scan their QR code. Shows your own identity public key and QR for them to scan back. Contact exchange is bidirectional — both parties must add each other.


Prerequisites

1. Yggdrasil Network

Ember requires Yggdrasil to be installed and running on your device (or accessible via your network). Yggdrasil provides the IPv6 address that Ember uses as your peer identity on the network.

2. Android Device

  • Android 8.0+ (API 26)
  • Camera (for QR scanning)
  • Internet access (for Yggdrasil peer connectivity)

Build

# Clone
git clone https://github.com/TheFruggg/Ember-5.0.git
cd Ember-5.0

# Set JAVA_HOME (Android Studio JBR recommended)
export JAVA_HOME=/path/to/android-studio/jbr

# Debug build
./gradlew assembleDebug

# APK output
# app/build/outputs/apk/debug/app-debug.apk

Build Variants

Variant Debug Logging ProGuard App ID Suffix
Debug Enabled Disabled .debug
Release Disabled Enabled

Permissions

Permission Purpose
INTERNET Yggdrasil P2P communication
CAMERA QR code scanning
POST_NOTIFICATIONS Incoming message alerts
FOREGROUND_SERVICE Background message listener
WAKE_LOCK Keep listener alive
ACCESS_NETWORK_STATE / ACCESS_WIFI_STATE Yggdrasil address detection

Privacy Model

Property Status
Central server None
Account registration None
Phone number required No
Metadata logging None
Messages stored server-side Never
Contact discovery Manual only
Cloud backup None (by design)
Encryption in transit AES-256-GCM (Double Ratchet)
Encryption at rest SQLCipher + EncryptedSharedPreferences

Project Structure

app/src/main/java/com/example/ember/
├─ data/
│  ├─ crypto/          # DoubleRatchet, MessageKeyStore
│  ├─ db/              # Room entities, DAOs, database
│  └─ network/         # YggdrasilClient, ListenerService, MessageBridge
├─ domain/
│  └─ ChatRepository   # Single source of truth for all data operations
├─ ui/
│  ├─ screens/         # Compose screens (Home, Chat, Contacts, Add, Details)
│  ├─ theme/           # EmberComponents, color palette, typography
│  └─ viewmodel/       # MVVM ViewModels per screen
└─ work/
   └─ TtlCleanupWorker # WorkManager job for expired message deletion

Roadmap

  • Group messaging UI (data layer already implemented)
  • In-app fingerprint comparison tool
  • Message reactions
  • Contact blocking
  • Full-text message search
  • Voice notes

Ember — because every conversation should burn after reading.

About

Serverless encrypted communications app

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages