Technical Deep Dive
Bluetooth Low Energy (BLE) Transport
Why BLE?
Bluetooth Low Energy provides the ideal transport layer for offline mesh networking:
Ubiquitous availability - Every modern smartphone has BLE hardware
Low power consumption - Designed for battery-constrained devices
No infrastructure required - Direct device-to-device communication
Reasonable range - 10-100m depending on environment and power class
Platform support - Native APIs on iOS and Android
Dual-Mode Architecture
anon0mesh operates BLE in dual-mode, allowing each device to simultaneously:
Central Role (Scanner)
Discovers nearby peripheral devices
Initiates connections to found peers
Reads characteristics from connected peripherals
Manages multiple simultaneous connections
Peripheral Role (Advertiser)
Broadcasts service UUID to announce presence
Accepts incoming connections from centrals
Exposes GATT characteristics for data exchange
Notifies connected centrals of new packets
This dual-mode operation creates a self-organizing mesh where every node can both discover and be discovered.
BLE Protocol Stack
┌─────────────────────────────────────┐
│ Application (Nostr Messages) │
├─────────────────────────────────────┤
│ Packet Layer (Serialization) │
├─────────────────────────────────────┤
│ GATT (Characteristics/Services) │
├─────────────────────────────────────┤
│ ATT (Attribute Protocol) │
├─────────────────────────────────────┤
│ L2CAP (Logical Link Control) │
├─────────────────────────────────────┤
│ Link Layer (BLE Radio) │
└─────────────────────────────────────┘Service and Characteristic Design
anon0mesh defines a custom GATT service with three characteristics:
TX Characteristic (Write)
Accepts incoming packets from connected peers
Write-without-response for low latency
MTU-aware chunking for large packets
RX Characteristic (Notify)
Pushes outgoing packets to subscribers
Notification-based for efficient delivery
Automatic packet queuing when peer unavailable
Metadata Characteristic (Read)
Exposes peer capabilities and protocol version
Read once during connection handshake
Used for protocol negotiation
BLE Constraints and Solutions
Challenge: 31-byte advertising limit
Solution: Advertise only service UUID, exchange data via characteristics
Challenge: ~512-byte MTU on most devices
Solution: Automatic fragmentation and reassembly for larger packets
Challenge: Connection limits (typically 7-10 simultaneous)
Solution: Priority-based connection management, rotate peers
Challenge: Android location permission requirement
Solution: Request at runtime with clear user explanation
Challenge: Background restrictions on iOS/Android
Solution: Use foreground service with persistent notification
Nostr Protocol Integration
What is Nostr?
Nostr (Notes and Other Stuff Transmitted by Relays) is a simple, open protocol for censorship-resistant social networks. anon0mesh adopts Nostr's cryptographic primitives for secure messaging without requiring internet connectivity.
Key Nostr Concepts
Identity (NIP-01)
Each user has a keypair: private key (nsec) and public key (npub)
Public key serves as universal identifier across all relays
Private key signs all messages, proving authenticity
Events (NIP-01)
All data is structured as events with:
Kind (type of event: 1=note, 4=encrypted DM, etc.)
Content (the actual message payload)
Tags (references, mentions, metadata)
Signature (ed25519 signature over serialized event)
Relays (NIP-01)
Servers that store and forward events
anon0mesh peers act as mobile relays over BLE for private messaging
Nostr Implementation Profiles (NIPs)
anon0mesh implements several key NIPs:
NIP-04: Encrypted Direct Messages
Uses shared secret derived via ECDH (Elliptic Curve Diffie-Hellman)
Content encrypted with AES-256-CBC
Simple but lacks forward secrecy
Suitable for basic private messaging
NIP-44: Versioned Encryption
Improved encryption scheme over NIP-04
Uses XChaCha20-Poly1305 AEAD cipher
Deterministic nonces from conversation key
Better security properties and performance
NIP-17: Private Direct Messages (Gift Wrap)
Implements forward secrecy through ephemeral keys
Each message uses one-time keypair
Content wrapped in sealed envelope
Even if long-term key compromised, past messages remain secure
┌──────────────────────────────────────┐
│ Gift Wrap Structure │
├──────────────────────────────────────┤
│ Ephemeral Key (one-time use) │
│ ├─ Encrypts inner event │
│ └─ Discarded after encryption │
│ │
│ Seal Event (kind 13) │
│ ├─ Encrypted with recipient pubkey │
│ └─ Contains actual message content │
│ │
│ Rumor (unsigned event) │
│ └─ The actual private message │
└──────────────────────────────────────┘Why Nostr for Mesh Networking?
Cryptographic primitives
Battle-tested ed25519 signatures
Well-specified encryption schemes
Interoperable key formats
Decentralized identity
No central authority required
Self-sovereign key management
Cross-platform compatibility
Event-based architecture
Natural fit for message passing
Flexible tagging system
Extensible event kinds
Developer ecosystem
Existing libraries (nostr-tools, etc.)
Documentation and specifications
Growing community
BLE + Nostr Integration
Message Flow
User A (Sender) User B (Receiver)
│ │
├─ Create Nostr event │
├─ Encrypt with NIP-17 │
├─ Serialize to compact packet │
│ │
├─ [BLE Central scans] │
├─ Discover peer B │
├─ Connect to peer B │
│ │
├─ Write packet to TX char ────────>
│ ├─ Receive via GATT
│ ├─ Deserialize packet
│ ├─ Validate TTL/signature
│ ├─ Decrypt with NIP-17
│ └─ Deliver to app
│ │
│ ├─ Should relay?
│ ├─ Decrement TTL
│ └─ Forward to other peersPacket Format
┌────────────────────────────────────────┐
│ Header (8 bytes) │
│ ├─ Magic (2 bytes): 0xAB0D │
│ ├─ Version (1 byte): 0x01 │
│ ├─ Type (1 byte): MSG/TXN/ACK │
│ ├─ TTL (1 byte): 0-255 hops │
│ ├─ Flags (1 byte): priority, etc │
│ └─ Length (2 bytes): payload size │
├────────────────────────────────────────┤
│ Packet ID (32 bytes) │
│ └─ SHA-256 hash for deduplication │
├────────────────────────────────────────┤
│ Nostr Event (variable length) │
│ └─ Serialized JSON or binary encoding│
├────────────────────────────────────────┤
│ Signature (64 bytes) │
│ └─ ed25519 signature over header+event│
└────────────────────────────────────────┘Optimizations
Compact Encoding
Binary serialization instead of JSON when possible
Compression for repeated fields
Omit unnecessary Nostr event fields for internal relay
Smart Relay Policy
Only relay messages with sufficient TTL
Rate limit relay to prevent flood attacks
Prioritize recent/undelivered messages
Connection Management
Maintain connection pool of active peers
Periodic reconnection to refresh topology
Graceful degradation when connection limit reached
Security Considerations
Threat Model
Passive Eavesdropper
Can observe BLE advertising
Cannot decrypt message contents (NIP-17)
Cannot link messages to real identity
Active Attacker
Can inject malicious packets
Mitigated by signature verification
Rate limiting prevents flood
Malicious Peer
Can refuse to relay
Cannot decrypt messages not addressed to them
Reputation system discourages bad behavior
Privacy Features
Forward Secrecy (NIP-17)
Ephemeral keys prevent retroactive decryption
Even if long-term key compromised, history safe
Metadata Protection
Gift wrap hides sender/recipient from relays
BLE MAC randomization (platform-dependent)
TTL prevents tracking via hop count
Traffic Analysis Resistance
Constant-rate padding (optional)
Dummy traffic generation
Onion-like layering possible via nested encryption
Performance Characteristics
Throughput
Single BLE connection
~1-2 KB/s sustainable throughput
MTU negotiation can improve to ~10 KB/s
Limited by GATT protocol overhead
Mesh network
Scales sub-linearly with peer count
Bottleneck: connection limit per device
Typical: 5-10 active connections
Latency
One-hop delivery
Connection establishment: ~500ms
Packet transmission: ~50-200ms
Total: <1 second for nearby peer
Multi-hop delivery
Add ~200-500ms per hop
3-4 hops practical maximum
Exponential TTL decay prevents excessive relay
Battery Impact
Moderate usage (checking every 5 min)
~2-5% battery per hour
Comparable to GPS navigation
Heavy usage (always-on mesh)
~5-8% battery per hour
Foreground service required for reliability
Platform-Specific Considerations
Android
Permissions
BLUETOOTH_SCAN- Required for discoveryBLUETOOTH_CONNECT- Required for GATT operationsBLUETOOTH_ADVERTISE- Required for peripheral modeACCESS_FINE_LOCATION- Required for BLE scan on Android <12
Background Restrictions
Doze mode limits background scanning
Use foreground service with notification
BLEManager for periodic sync
iOS
Background Modes
Enable "Uses Bluetooth LE accessories"
Limited to specific service UUIDs
~10 seconds per background wake
Privacy
User must approve Bluetooth usage
Location services not required (unlike Android)
More restrictive background operation
Future Enhancements
Protocol Evolution
NIP-59: Gift Wrapped Sealed Sender
Even stronger metadata protection
Prevents relay from knowing recipient
Multi-path routing
Send packet via multiple peers
Increases reliability and censorship resistance
Onion routing
Layer multiple encryption levels
Each hop peels one layer
Complete sender/receiver anonymity
Performance Improvements
Better compression
Protocol buffer encoding
Delta compression for updates
Adaptive based on content type
Connection multiplexing
Multiple logical channels per BLE connection
Priority queuing per channel
Reduces connection churn
Mesh topology optimization
Cluster formation algorithms
Hierarchical routing for large networks
Geographic-aware peer selection
Last updated
