
blue_ghost
system design
Architecture Overview
blue_ghost is built as a layered, offlineβfirst secure communication system. Each layer is isolated, minimal, and designed to eliminate entire classes of attack.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Application UI β β (Jetpack Compose, MVVM) β ββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ€ β Session Manager β Secure Input / Display β β (BleManager.kt) β (Password-mode keyboard, β β β FLAG_SECURE screenshots) β ββββββββββββββββββββββββ΄βββββββββββββββββββββββββββββββ€ β Cryptographic Protocol Layer β β Ephemeral ECDH Β· Double Ratchet Β· AES-256-GCM β β HKDF-SHA256 Β· Replay Window Β· Safety Number β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ€ β Bluetooth Low Energy Transport β β (GATT Server + Client, BLE Advertiser) β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ€ β Android Keystore (TEE-backed) β β P-256 identity key β never extracted β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Component Breakdown
- Identity Manager β hardware-backed P-256 keys in Android Keystore TEE
- Handshake Engine β ephemeral ECDH (P-256) with HKDF-SHA256 key derivation
- Ratchet Engine β Double Ratchet state machine (symmetric + DH ratchet)
- Message Encryptor β AES-256-GCM with authenticated sequence numbers
- BLE Transport β GATT server/client, BLE advertiser/scanner
- Session Manager β lifecycle, reconnection, and Seal Ceremony teardown
- Privacy Layer β password-mode input, FLAG_SECURE screen protection, notification redaction
ECDH Handshake Flow
Device A (initiator) Device B (responder)
ββββββββββββββββββββ ββββββββββββββββββββ
Generate EKa (ephemeral)
Send EKa.public βββββββββββββββββββββββΆ Generate EKb (ephemeral)
shared = ECDH(EKb.priv, EKa.pub)
Derive via HKDF-SHA256 β
rootKey (32 bytes)
recvChainKey (32 bytes)
sendChainKey (32 bytes)
βββββββββββββββββββββββ Send EKb.public
shared = ECDH(EKa.priv, EKb.pub)
Derive via HKDF-SHA256 β
rootKey (32 bytes)
sendChainKey (32 bytes)
recvChainKey (32 bytes)
Both sides now hold identical ratchet initialisation state.
No private material was ever transmitted.
Double Ratchet Flow
ββββββββββββββββββββ
β Root Key (RK) β β initialised from HKDF handshake output
ββββββββββ¬ββββββββββ
β (advances on each DH ratchet step)
βΌ
ββββββββββββββββββββ
β DH Ratchet β β new ephemeral keypair generated per turn
β (break-in recov) β
ββββββββββ¬ββββββββββ
β
βΌ
ββββββββββββββββββββ
β Chain Key (CK) β β HMAC-SHA256 ratchet, one step per message
ββββββββββ¬ββββββββββ
β
βΌ
ββββββββββββββββββββ
β Message Key (MK) β β used once for AES-256-GCM, then wiped
ββββββββββββββββββββ
Each message uses a unique MK that is deleted immediately after use. The DH ratchet step re-derives RK and CK from a new ECDH output, ensuring that a future key compromise cannot retroactively expose past messages.
BLE Transport Model
blue_ghost uses BLE GATT characteristics as an encrypted bidirectional pipe. The advertiser broadcasts a minimal service UUID with avatar seed and busy-status bytes. Descriptions and names are fetched via GATT read on first contact.
ββββββββββββββββββββββββββββββββββββ
β BLE Advertisement β
β Service UUID + avatar seed β
β + busy flag (5 bytes total) β
ββββββββββββββββ¬ββββββββββββββββββββ
β connect
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββ
β GATT Service: blue_ghost β
βββββββββββββββββββββββββββββββββββββββββββββββ€
β NAME_CHAR (read) β
β DESC_CHAR (read) β
β SHAKE_CHAR (write) β handshake + control β
β MESSAGE_CHAR (write) β encrypted payloads β
βββββββββββββββββββββββββββββββββββββββββββββββ
All message payloads are uniform-length encrypted blobs. No plaintext, metadata, or identifiers are ever transmitted in the clear.
Session Lifecycle
[ Set name + description ]
β
βΌ
[ Start scanning + advertising ]
β
βΌ
[ Peer discovered β tap to view profile ]
β GATT probe reads NAME + DESC
βΌ
[ Connect dialog β send SHAKE ]
β SHAKE payload: ephemeral pub + avatar + name + desc
βΌ
[ Peer accepts β ACCEPT payload returned ]
β ACCEPT payload: ephemeral pub + avatar + name + desc
βΌ
[ HKDF derives root + chain keys ]
β
βΌ
[ Double Ratchet active β encrypted messaging ]
β
βΌ
[ Session end β Seal Ceremony ]
β
βΌ
[ All keys + history destroyed ]