Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/permissionlesstech/bitchat/llms.txt

Use this file to discover all available pages before exploring further.

This page is an honest analysis of what the Bitchat protocol protects, what it exposes, and what its current limitations are. Bitchat is used by people in hostile network environments. A realistic security posture requires understanding not just what the protocol encrypts, but what it does not — and what an adversary in radio range, on the network path, or controlling a relay can observe.
Metadata is the primary attack surface. The 8-byte sender ID in every mesh packet is derived from the device’s non-rotating Noise static key. Signed announcements publish static keys and nicknames in cleartext. A passive listener with radio access can enumerate participants, track devices across time and place, and reconstruct the local adjacency graph. Encrypting message content does not prevent this. See Metadata is the Weakest Link for the full analysis.

What Relay Nodes Cannot Do

Relay nodes on the BLE mesh are any connected peer that forwards packets. They are not trusted infrastructure. A relay node in the mesh:
  • Cannot read private message content. Private payloads travel inside Noise XX sessions as typed ciphertext. Relays see opaque noiseEncrypted packets — the packet type is visible, but the content is not.
  • Cannot forge private messages. Noise XX provides mutual authentication and integrity. A tampered ciphertext fails the Poly1305 tag check and is dropped.
  • Cannot impersonate a peer without possessing that peer’s Curve25519 static private key.
  • Can drop packets. Flooding with copy budgets and sender outbox retransmission mitigate accidental or deliberate drops, but a relay that drops all traffic toward a peer is indistinguishable from a disconnected link.
Padding applies only to noiseEncrypted and noiseHandshake packets. All other packet types — public messages, announcements, board posts, group messages, fragments, and voice frames — relay at their natural length. Payload sizes for most traffic are observable by relay nodes.

What Couriers Cannot Do

Couriers are peers who physically carry sealed envelopes for offline delivery. The courier system is quota-bounded and content-opaque:
  • Cannot read envelope content. Courier envelopes are sealed with Noise X to the recipient’s static key. The courier holds opaque ciphertext.
  • Cannot link envelopes across days. The recipient addressing tag is an HMAC of the recipient’s static key and the UTC day. Tags rotate daily, so a courier cannot correlate a Monday envelope with a Tuesday one for the same recipient.
  • Cannot amplify. Each envelope carries a copy budget (initially up to 4, capped at 8 across the spray-and-wait diffusion process). A courier meeting an eligible peer hands over half the remaining budget. Replaying a deposit does not increase the budget.
  • Can drop mail. Redundant copies (up to 3 distinct couriers) and sender outbox retransmission mitigate deliberate drops. Couriered mail from blocked senders is dropped at decryption time by the recipient, not at delivery.
Trust tiers limit deposit volume: mutual favorites may deposit 5 envelopes each; any peer with a signature-verified announcement may deposit 2, into a bounded pool (20 of 40 slots) that can never crowd out favorites’ mail.

Flooding Abuse Mitigations

The controlled-flood architecture includes several bounds on abuse:
Packets originate with TTL 7. Dense graphs (≥ 6 links) cap broadcast TTL at 5; thin chains (≤ 2 links) relay at full depth. A packet cannot propagate indefinitely.
An LRU seen-set (1,000 entries, 5-minute expiry) keyed by sender, timestamp, type, and payload digest drops duplicates. A scheduled relay is cancelled when a duplicate arrives first from another relay.
Courier deposits are bounded by trust tier. No single peer can fill the courier pool; favorites and verified-announce tiers have separate slot allocations.
The Noise layer enforces per-peer handshake rate limits (10 per minute) and global limits (30 per minute). Announcements back off from every-4-seconds (isolated) to every 15–30 seconds (connected).

Replay Protection

Public broadcast messages: Bounded by a 6-hour acceptance window plus the deduplication seen-set. Messages older than 6 hours are not accepted into the gossip cache and will not be relayed. The gossip-synced history cache holds 1,000 packets. Private payloads: Protected by Noise nonces. NoiseCipherState implements a sliding-window replay protection scheme tracking received nonces in a 1,024-message window. Nonces that fall below the window floor (too old) or have already been seen within the window are rejected. This is the most critical section on this page. The protocol’s content encryption is sound, but metadata exposure is significant and currently unmitigated at the radio layer. Stable peer IDs. The 8-byte sender ID in every mesh packet header is the first 8 bytes of the SHA-256 fingerprint of the device’s Curve25519 Noise static key. This key never rotates across sessions, reboots, or reinstalls that preserve the keychain. The peer ID is therefore stable for the lifetime of a device identity. A passive listener can recognize a specific device across sessions and locations. Cleartext announces. Signed announcements propagate multi-hop and carry the following in cleartext:
  • The device nickname
  • The full Noise static public key (Curve25519)
  • The Ed25519 signing public key
  • Up to 10 direct-neighbor IDs
This means a passive radio receiver can enumerate participants and link a device across time and place without breaking any encryption. The fixed BLE service UUID makes any Bitchat device detectable as running the app by any scanner in range. Adjacency graph reconstruction. Announces carry up to 10 direct-neighbor IDs (§4.3 of the whitepaper). A single sniffer in range of a node can read not just that node’s identity, but the identities of all its immediate neighbors — reconstructing the local mesh topology. Hop distance reveals origin. Origin packets leave at the default TTL (7). A receiver can infer the approximate hop distance to the originator from the TTL of the received packet. Combined with multiple observation points, this can narrow down the originator’s physical location. What does help:
  • Daily-rotating courier tags limit correlation of carried mail across days. An adversary watching a courier’s deposits cannot link Monday’s envelope to Tuesday’s for the same recipient.
  • Nostr traffic over Tor hides the device IP from relay operators. With Tor enabled and enforced, no relay operator learns the client’s IP address.
What does not help at the radio layer: BLE address randomization managed by iOS does not deliver the unlinkability it might suggest. The application layer publishes stable identifiers above the MAC layer, so a passive scanner can recognize a device regardless of its Bluetooth MAC address rotation. Addressing the radio-layer exposure is documented as future work; see Future Work.

Known Limitations

No Forward Secrecy: Courier Envelopes

Courier envelopes are sealed with Noise X to the recipient’s static Curve25519 key. Compromise of the static key exposes sealed-but-undelivered mail.

No Forward Secrecy: Nostr Envelopes

Nostr private envelopes derive keys from the recipient’s static secp256k1 Nostr key via ECDH. Compromise of the static Nostr key exposes stored envelopes on relays.

Nostr Relay Retention

Relay operators can retain published events indefinitely. Public events (location channels, bridge traffic) may be copied to third-party services outside project control.

Payload Length Observability

Only noiseEncrypted and noiseHandshake packets are padded. All other packet types relay at natural length. A relay node can observe ciphertext sizes for most traffic types.

Vulnerability Reporting

Use GitHub’s private vulnerability reporting: navigate to the Security tab of the repository and select “Report a vulnerability.” Do not open a public issue for anything that could put people at risk before a fix ships. Bitchat is used by people in hostile network environments; a public proof-of-concept can be acted on faster than a patch can reach them. A useful report describes what an attacker can do, which build is affected (App Store version or commit hash), and how to reproduce the issue. A failing test or a packet capture is worth more than a description of potential impact. This is a volunteer-maintained project. The aim is to acknowledge reports within a week and to move on confirmed vulnerabilities immediately — historically, confirmed protocol and key-handling issues have been fixed within days. There is no bug bounty. Fixes ship to the latest App Store release and main; older releases are not patched.

In-Scope Vulnerabilities

The following properties are what the app promises, and findings that compromise them are in scope:
  • Confidentiality and integrity of private messages and media — Noise sessions over BLE; Bitchat’s proprietary private-envelope format over Nostr (not NIP-17/NIP-44/NIP-59)
  • Identity: key handling, verification, impersonation, session binding
  • Panic wipe completeness — the panic action must destroy what it claims to destroy
  • Metadata exposure beyond what is documented here — additional linkability or tracking not already described
  • Downgrade paths — anything that silently moves traffic from an encrypted path to a plaintext one
  • Tor bypass — anything that makes traffic bypass Tor while the Tor preference is on
  • Supply-chain integrity — tampering with source or vendored binaries

Out-of-Scope

The following are documented design properties, not vulnerabilities:
  • Public visibility of mesh announces and geohash channels — broadcast content, nicknames, and public keys are public by design
  • Bluetooth proximity being observable — anyone in radio range can detect that a BLE device is present
  • Mesh flooding and relay behavior — rate limits exist; the broadcast mesh topology is what it is
  • Behavior of third-party Nostr relays — relay operator decisions are outside project control
  • Denial of service requiring physical proximity and battery-drain attacks in general
If you are unsure whether something is in scope, report it privately anyway. A false alarm costs a few minutes; a real issue reported publicly can cost much more.

Future Work

The following improvements to the metadata and forward-secrecy situation are planned or under consideration (from the whitepaper §9):
Epoch-rotating peer IDs, with static-key disclosure moved inside the encrypted handshake. Mutual favorites would recognize each other through a tag derived from their shared secret, so presence would stop being linkable across sessions. This addresses the most significant current metadata exposure.
A prekey scheme would allow courier envelopes to derive per-message keys rather than encrypting directly to the recipient’s static key, providing forward secrecy for sealed mail. This is the single most impactful cryptographic improvement for the courier path.
Extending length-hiding padding to public messages, announcements, and other currently unpadded packet types. Also closing the current gap where frames requiring more than 255 bytes to reach a padding bucket are emitted unpadded.
Making the neighbor ID list in announcements optional, or restricting it to authenticated links, to reduce adjacency graph leakage from a single announcement packet.
For user-facing privacy details and the full list of what the app persists, see Privacy Assessment.

Build docs developers (and LLMs) love