# How BitChat Enables Decentralized Peer-to-Peer Messaging: Bluetooth Mesh and Nostr Protocol

> Discover how BitChat achieves decentralized peer-to-peer messaging using Bluetooth mesh for local offline chat and Nostr for global reach, ensuring secure communication.

- Repository: [permissionlesstech/bitchat](https://github.com/permissionlesstech/bitchat)
- Tags: deep-dive
- Published: 2026-08-23

---

**BitChat enables decentralized peer-to-peer messaging by combining a Bluetooth mesh network for offline local communication with the Nostr relay network for global internet reach, using Noise encryption for Bluetooth links and custom XChaCha20-Poly1305 private envelopes for Nostr transport.**

BitChat, developed by `permissionlesstech/bitchat`, implements a hybrid architecture that ensures message delivery regardless of internet connectivity. The system automatically routes communications through a local Bluetooth mesh when offline, falling back to Nostr relays when WAN access is available, all while maintaining end-to-end encryption across both transports.

## Dual-Transport Architecture

BitChat operates on two complementary transport layers that share a common cryptographic foundation. This design ensures that users can exchange messages in completely offline environments while retaining the ability to reach global recipients when connected.

- **Bluetooth Mesh Layer**: Handles direct, local-area communication without internet access. Implemented primarily in [`BLEService.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLEService.swift), this layer manages device discovery, multi-hop routing, and link-level encryption using the Noise protocol.
- **Nostr Relay Network**: Provides global reach through public Nostr relays. The [`NostrProtocol.swift`](https://github.com/permissionlesstech/bitchat/blob/main/NostrProtocol.swift) file implements BitChat-specific private envelopes that encrypt messages using XChaCha20-Poly1305 before transmission over standard Nostr infrastructure.

Both layers use the same message packet model, ensuring consistent end-to-end security regardless of which transport handles the data.

## Bluetooth Mesh Transport for Offline Messaging

The Bluetooth mesh functionality transforms mobile devices into nodes of a multi-hop ad-hoc network capable of relaying messages across physical distances without internet infrastructure.

### Discovery and Link Establishment

The `BLERadioController` within [`BLEService.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLEService.swift) manages device discovery by scanning for the BitChat service UUID (`F47B5E2D‑…‑B5C`). The implementation supports both central and peripheral roles simultaneously, allowing devices to accept incoming connections while actively scanning for peers.

Each established link initiates a Noise-IK handshake through `NoiseEncryptionService` to derive a unique shared secret. This provides forward secrecy and authentication for all subsequent traffic on that specific Bluetooth connection, stored and tracked in [`BLELinkAuthState.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLELinkAuthState.swift).

### Packet Structure and Binary Protocol

Messages transmitted over Bluetooth use a compact binary format defined in [`BinaryProtocol.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BinaryProtocol.swift). The `BitchatPacket` structure includes:

```swift
let packet = BitchatPacket(
    type: MessageType.message.rawValue,
    senderID: myPeerID.data,
    recipientID: nil,
    timestamp: UInt64(Date().timeIntervalSince1970 * 1000),
    payload: Data(envelope.jsonString().utf8),
    signature: nil,
    ttl: TransportConfig.messageTTLDefault
)
let binary = BinaryProtocol.encode(packet)!   // padded for BLE MTU

```

The binary protocol encodes a header containing version, type, TTL, timestamp, flags, and payload length, followed by sender/recipient IDs, optional route hops, optional compression preamble, the encrypted payload, and an optional signature. This format minimizes airtime usage while supporting mesh routing features.

### Fragmentation and Reassembly

Given BLE MTU limitations, large messages undergo fragmentation handled by `BLEOutboundFragmentTransferScheduler` and [`BLEFragmentHandler.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLEFragmentHandler.swift). The `BLEFragmentAssemblyBuffer` reconstructs incoming fragments into complete messages before decryption and delivery to the application layer.

### Routing and Deduplication

When a packet includes the `hasRoute` flag, peers forward it hop-by-hop until it reaches the destination or the TTL expires. The `BLESelfBroadcastTracker` and `MessageDeduplicator` prevent routing loops and duplicate processing, ensuring efficient bandwidth utilization in dense mesh networks.

## Nostr Protocol Integration for Global Reach

When Bluetooth peers are unavailable, BitChat seamlessly transitions to Nostr relays while maintaining message confidentiality through a proprietary envelope format incompatible with standard NIP-44.

### BitChat Private Envelope Construction

The [`NostrProtocol.swift`](https://github.com/permissionlesstech/bitchat/blob/main/NostrProtocol.swift) file implements a three-layer envelope system:

1. **Rumor Creation**: Generate an unsigned `NostrEvent` of kind 14 (DM) containing the plaintext message.
2. **Seal Encryption**: Encrypt the rumor with the recipient’s public key using `createSeal`, then sign the sealed event with the sender’s long-term Schnorr key.
3. **Gift-Wrap**: Encrypt the sealed event with a freshly generated ephemeral Schnorr key using `createGiftWrap`, producing a kind 1059 event.

The resulting envelope format (`v2:` + Base64URL(nonce || ciphertext || tag)) uses HKDF-derived symmetric keys and XChaCha20-Poly1305 authenticated encryption. This process ensures that Nostr relays only store opaque ciphertext while preserving sender authentication.

### Automatic Transport Fallback

The transport selection logic resides in `BLEService.sendMessage` and the `ChatTransportEventCoordinator`. When invoked, the system first attempts transmission via `sendPrivateMessage` over the Bluetooth mesh. If no path exists, the message undergoes the private envelope creation process described above and publishes via `NostrRelayManager`.

Incoming Nostr events trigger `decryptPrivateMessage`, which unwraps the gift-wrap and seal layers to extract the inner rumor’s content for UI delivery.

## End-to-End Security Implementation

BitChat employs transport-specific encryption mechanisms that provide defense in depth:

- **Bluetooth Links**: Noise-IK handshakes establish per-link encryption with forward secrecy, implemented in `NoiseEncryptionService`.
- **Nostr Transport**: XChaCha20-Poly1305 via `XChaCha20Poly1305Compat` provides authenticated encryption for the private envelope, while Schnorr signatures verify sender identity.
- **Optional Compression**: The `BinaryProtocol` applies zlib compression only when it reduces payload size, storing the original length for safe decompression.

All cryptographic primitives are wrapped in type-safe services and validated before use, ensuring that private keys never leave the secure enclave during normal operations.

## Practical Implementation Examples

To send a message through BitChat’s automatic transport selection:

```swift
// Send a text message – the service picks the best transport automatically
bleService.sendMessage(
    "Hello from the mesh!",
    mentions: [],
    to: nil          // nil ⇒ public broadcast; give a PeerID for a DM
)

```

For testing or manual relay transmission, construct a private envelope directly:

```swift
// Build a BitChat private envelope manually (useful for testing)
let envelope = try NostrProtocol.createPrivateMessage(
    content: "Secret hello",
    recipientPubkey: recipientPubkeyHex,
    senderIdentity: myNostrIdentity
)

```

## Summary

- BitChat achieves **decentralized peer-to-peer messaging** through a dual-layer architecture combining Bluetooth mesh and Nostr relays.
- The **Bluetooth mesh layer** ([`BLEService.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLEService.swift)) provides offline capability via multi-hop routing, Noise-IK encryption, and adaptive fragmentation.
- The **Nostr layer** ([`NostrProtocol.swift`](https://github.com/permissionlesstech/bitchat/blob/main/NostrProtocol.swift)) enables global reach using a proprietary gift-wrap/seal/rumor envelope format with XChaCha20-Poly1305 encryption.
- **Automatic fallback logic** attempts Bluetooth delivery first, transitioning to Nostr relays only when mesh connectivity is unavailable.
- All communications maintain **end-to-end encryption** appropriate to their transport, with no plaintext exposure to intermediaries or relays.

## Frequently Asked Questions

### How does BitChat handle messaging without internet connectivity?

BitChat uses a Bluetooth mesh network where devices act as relays for one another. When you send a message, [`BLEService.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLEService.swift) attempts to transmit it through local Bluetooth connections using `sendPrivateMessage`. If the recipient is not directly in range, other BitChat devices forward the packet hop-by-hop until delivery or TTL expiration, all without requiring internet access.

### What encryption standards does BitChat use for decentralized peer-to-peer messaging?

BitChat employs two complementary encryption schemes. For Bluetooth links, it uses **Noise-IK handshakes** (`NoiseEncryptionService`) to establish forward-secure channels between directly connected peers. For Nostr transport, it uses **XChaCha20-Poly1305** authenticated encryption within a custom private envelope format ([`NostrProtocol.swift`](https://github.com/permissionlesstech/bitchat/blob/main/NostrProtocol.swift)), combined with Schnorr signatures for sender verification.

### How does BitChat prevent infinite message loops in the Bluetooth mesh?

The implementation includes `BLESelfBroadcastTracker` and `MessageDeduplicator` services that maintain seen-message caches. Additionally, every `BitchatPacket` contains a TTL (time-to-live) field decremented at each hop. When TTL reaches zero or a device recognizes it has already processed the message ID, forwarding stops immediately, preventing broadcast storms and bandwidth exhaustion.

### Is BitChat compatible with standard Nostr clients?

No, BitChat uses a proprietary private envelope format (`v2:` + Base64URL encoding) that is incompatible with NIP-44. While the underlying Nostr event structure follows Nostr protocol specifications (using kind 1059 for gift-wraps), the specific HKDF key derivation and XChaCha20-Poly1305 implementation in [`NostrProtocol.swift`](https://github.com/permissionlesstech/bitchat/blob/main/NostrProtocol.swift) are unique to BitChat. Standard Nostr clients cannot decrypt BitChat messages without implementing the same cryptographic pipeline.