Mesh Stacks Compared: MeshCore, Meshtastic, BitChat
Status: Research note — July 2026
Three off-grid mesh messaging stacks are in active real-world deployment today: Meshtastic and MeshCore on LoRa radio hardware, and BitChat on phone-to-phone BLE. All three deliver messages with no internet, no cellular network, and no operator. None of them is the system described in our Vision — but each has already solved a problem we would otherwise solve from scratch, and each has made a mistake we can avoid paying for twice.
This page compares them on the axes that matter to our design: routing behaviour, cryptography, metadata exposure, identity and trust establishment, hardware cost, and project governance. It closes with what we should take from each, and what it means for Prototype 7 (LoRa Radio Mesh) and Prototype 2 (BLE Messenger).
The three are complementary rather than competing: Meshtastic and MeshCore are radio stacks running on dedicated hardware at kilometre range; BitChat is a phone stack running on hardware everybody already carries, at room range. Comparing them head-to-head on range or bandwidth is a category error. Comparing them on routing discipline, key handling, and metadata leakage is not — and that is where they diverge sharply.
At a Glance
| Meshtastic | MeshCore | BitChat | |
|---|---|---|---|
| Transport | LoRa (868/915 MHz ISM) | LoRa (868/915 MHz ISM) | Bluetooth LE + Nostr relays |
| Hardware needed | Dedicated radio (~$19–45) | Dedicated radio (~$19–45) | None — phone only |
| Range per hop | 2–10 km line of sight | 2–10 km line of sight | 10–30 m |
| Routing | Managed (controlled) flooding + learned next-hop for DMs | Flood to discover, then source-routed direct path | Adaptive TTL flooding with jitter |
| Hop limit | 3 default, 7 max | Configurable, path ≤ 64 hashes | TTL 7 at origin, adaptive down to 5 |
| Node roles | All nodes relay (Router/Repeater prioritised) | Enforced: companion / repeater / room server / sensor | All phones relay |
| Identity | 4-byte node ID + curve25519 keypair | Ed25519 keypair, 1-byte hash used for routing | Ephemeral Curve25519 + Ed25519 per install/area |
| Channel crypto | AES-256-CTR, pre-shared key | AES-128-ECB, pre-shared or SHA256("#room")[:16] |
Noise XX session (ChaCha20-Poly1305) |
| Direct-message crypto | curve25519 PKC + signature (≥ 2.5.0) | X25519 ECDH static shared secret | Noise XX — mutual auth + forward secrecy |
| Forward secrecy | No (documented) | No | Yes on live sessions; no on offline seals |
| Message integrity | Not verified on channel messages (documented) | HMAC-SHA256 truncated to 2 bytes | AEAD tag (full) |
| Store-and-forward | No (live mesh only) | Yes — room servers | Yes — outbox + courier envelopes |
| Licence | GPL-3.0 firmware | MIT core; T-Deck firmware and official mobile apps closed | MIT |
| Governance | Foundation-backed, stable | Trademark dispute unresolved (2026) | Single-sponsor project, no published audit |
| Physical-first trust | No | No | No |
| Post-quantum | No | No | No |
Meshtastic
What it is. The incumbent. Open-source GPL-3.0 firmware for ESP32 and nRF52840 LoRa boards, paired to a phone over BLE, with mature apps on Android, iOS, and desktop. It is the stack our P7 spec currently builds on, and its ecosystem — flasher, protobuf API, Python bindings, community range data — is by a wide margin the most complete of the three.
Routing. Managed flooding. Every node rebroadcasts, but a node that hears someone else rebroadcast the same packet first stays quiet. The contention window is scaled by SNR, so the node that received the weakest signal — inferred to be the most distant — gets the shortest backoff and rebroadcasts first, pushing packets outward rather than back into the middle. Nodes in the Router and Repeater roles rebroadcast regardless. Since firmware 2.6, direct messages are smarter: the first DM floods to find the destination, then the relay that carried the reply is recorded as the next hop and used for subsequent traffic, falling back to flooding if the link degrades.
Managed flooding (Meshtastic)
A ──► B ──► D ──► F every node rebroadcasts once,
│ │ ▲ unless it already heard the
└──► C ──► E ┘ rebroadcast from a neighbour.
Contention window ∝ 1/distance (SNR).
Cost: ~n transmissions per delivered packet.
Crypto. Channel payloads are AES-256-CTR under a pre-shared channel key. The default public channel (LongFast) uses the universally known key AQ== — it is a convenience default, not a security boundary. Since 2.5.0, direct messages use curve25519 public-key encryption plus a signature. The packet header is always cleartext so that nodes can relay traffic they cannot read.
What the project itself documents as missing: no perfect forward secrecy (a compromised channel key retroactively decrypts captured traffic — harvest-now-decrypt-later applies), no integrity verification on channel messages, and node identification derived from manufacturer MAC addresses, which makes impersonation trivial for anyone holding the channel key.
Scaling. The cleartext header carries the node ID, hop count, and routing state, and default configurations broadcast position and telemetry. From firmware 2.4.0 the firmware throttles ancillary traffic on meshes above 40 recently-seen nodes — ScaledInterval = Interval × (1 + (N − 40) × 0.075) — which is a mitigation, not a fix. In duty-cycle-limited regions with hundreds of visible nodes, and with many users setting hop limit to 7 against the recommended 3, airtime saturation and dropped traffic are the normal condition rather than the exception.
Relevance to us. Meshtastic is the right testbed and the wrong security layer — which is precisely how P7 already uses it: a bandwidth and duty-cycle harness underneath our own encrypted envelope. Its cleartext node ID is the same leak recorded as Gap 5 in the anonymity coverage matrix, and this page does not resolve it.
MeshCore
What it is. A lightweight MIT-licensed C++ mesh library for embedded radios, created by Scott Powell in late 2024 and published in January 2025, with web and mobile clients by Liam Cottle. It runs on the same LoRa boards as Meshtastic
and is not interoperable with it — different wire protocol, different crypto, different assumptions.
Roles are enforced, not advisory. This is the central design difference from Meshtastic:
- Companion — the user's node, paired to a phone over BLE/USB/WiFi. Companions do not repeat at all, deliberately, so that handheld nodes with poor placement cannot become bad routing paths.
- Repeater — the only role that forwards. Sited intentionally, usually elevated and mains- or solar-powered.
- Room server — a store-and-forward bulletin board holding shared posts, so a node that was absent can catch up.
- Sensor — telemetry endpoint with alerting.
Routing. Flood to discover, then direct. A first packet floods; each repeater appends its own 1-byte hash (the first byte of its Ed25519 public key) to a path field and retransmits once. The accumulated path is a route back, and subsequent packets are source-routed: the header carries the remaining hop list, each repeater strips itself and forwards to the next. Only repeaters participate. The path field holds up to 64 hashes.
Path learning (MeshCore)
discovery: C ──flood──► R1 ──► R2 ──► R3 ──► C' path = [r1,r2,r3]
thereafter: C ──direct──► R1 ──► R2 ──► R3 ──► C'
Cost: ~1 transmission per hop per packet, and only repeaters transmit.
Companion nodes never relay — a phone in a pocket cannot poison the route.
The airtime saving over flooding is real and is the reason MeshCore scales better in dense, planned deployments. The cost is that the mesh no longer self-organises out of whatever nodes happen to be present: without a repeater in range, a companion is isolated. MeshCore trades spontaneity for efficiency, which is the correct trade for a planned regional network and the wrong one for an ad-hoc crowd.
Crypto — read this before building on it. Ed25519 identities, X25519/ECDH shared secrets precomputed per contact when the contact is added, and adverts signed with Ed25519 to prevent spoofed announcements. Then:
- AES-128-ECB, with payloads (4-byte timestamp + 1-byte flags + message) zero-padded to the block size rather than PKCS#7. ECB has no semantic security: identical plaintext blocks under the same key produce identical ciphertext blocks.
- HMAC-SHA256 truncated to 2 bytes. A 1-in-65 536 forgery probability per attempt is not a meaningful integrity guarantee against an attacker who can transmit repeatedly, let alone one brute-forcing offline.
- No forward secrecy at all — static long-term keys, no ratchet, no ephemeral exchange. Key compromise is retroactive over the full message history.
- Replay protection is timestamp-based: repeaters enforce monotonically advancing timestamps per public key, with a 2-bit attempt counter in the flags to distinguish retransmissions.
- Private keys use a non-standard layout (first 32 bytes are a pre-clamped scalar, skipping the usual
clamp(sha512(seed))step), so standard crypto libraries misbehave if handed a MeshCore key directly.
These are defensible choices for timestamped, low-frequency, low-sensitivity radio traffic on constrained microcontrollers. They are not a foundation for a system whose stated goal is structural privacy. For our purposes this is not disqualifying — our design already treats the radio layer as untrusted and carries its own E2E envelope — but it does mean MeshCore's crypto must be treated as a checksum, not as protection.
Openness and governance — a live risk. The core firmware and libraries are MIT, but the T-Deck firmware and the official Android/iOS apps are closed source. More significantly, as of July 2026 the project is in an unresolved trademark dispute: a former core contributor filed for the "MeshCore" mark in the UK (29 March 2026) and EU (20 April 2026); the founder-led team counter-filed in New Zealand (11 April 2026), Australia (6 May 2026), and further jurisdictions through 4 June 2026, and is publicly fundraising for roughly $18 000 in legal costs. Development also spans more than one GitHub organisation (ripplebiz and meshcore-dev), and each side accuses the other of misconduct — closed-source AI-assisted appropriation on one hand, bad-faith brand capture on the other.
We do not need to take a side, and this page does not. The engineering consequence is what matters: the name, the canonical repository, and the maintainer set may all change. Any dependency should pin a specific commit of a specific fork and record why. Compare Meshtastic's foundation-backed governance and single canonical GPL-3.0 repository — for a multi-year research project, that difference is worth more than a routing optimisation.
BitChat
What it is. A phone-only BLE mesh chat app, MIT-licensed, released July 2025 by Jack Dorsey's team and iterating fast (Android 1.7.x by July 2026). No radio hardware, no accounts, no phone numbers, no servers in the local case. It is already covered as Option 7 in Implementation Options and in Existing Protocols; this section adds the wire-level detail relevant to P2.
Routing. Adaptive TTL flooding over BLE, tuned by observed local density:
- Packets originate with TTL 7. In dense graphs (6+ links) relays cap TTL at 5; in sparse chains (≤ 2 links) the full TTL is relayed.
- Rebroadcast jitter is 10–220 ms, widening as density increases — the BLE equivalent of Meshtastic's SNR contention window, solving the same broadcast-storm problem with a different signal.
- Duplicate suppression is an LRU cache of 1000 entries with 5-minute expiry, keyed on sender, timestamp, type, and payload digest.
Wire format. A compact binary header (version, type, TTL, timestamp, flags), an 8-byte sender ID, an optional 8-byte recipient ID, the payload, and an optional Ed25519 signature. Fragments are ~469 bytes to fit BLE MTU constraints, with 128 concurrent reassemblies and a 1 MiB cap per message.
Crypto. Two long-term keypairs per device — a Curve25519 static key for Noise agreement and an Ed25519 signing key. Live sessions use the Noise XX pattern (Curve25519 / ChaCha20-Poly1305 / SHA-256) for mutual authentication and forward secrecy. This is the strongest of the three by a distance, and it is a standard, analysed construction rather than a bespoke one. Offline "courier" seals fall back to the one-way Noise X pattern, which has no forward secrecy — acknowledged by the project as the main cryptographic trade-off of the offline path, pending a prekey scheme.
Store-and-forward. The sender outbox holds up to 100 messages per peer for 24 hours with 8 resend attempts. Public history caches 1000 packets over a 6-hour sync window (15 minutes for fragments). Courier envelopes are capped at 16 KiB and 24 hours, with 20 of 40 slots reserved for favourited contacts. Couriers are quota-bounded mailbags: they cannot read content, but they can drop it.
Internet path. When BLE cannot reach, BitChat uses Nostr — NIP-17 gift-wrapped DMs across a large public relay set, and geohash channels at block (7 chars), neighbourhood (6), city (5), province (4), and region (2) precision, with a fresh cryptographic identity per geohash area.
Security posture. In 2025, researcher Alex Radocea disclosed a broken identity-authentication path in the Favorites flow enabling contact impersonation via MITM; Dorsey added a warning that the app "may contain vulnerabilities and does not necessarily meet its stated security goals". Trail of Bits published a measured analysis of the episode, and no formal third-party audit has been published as of July 2026. The current codebase has moved to the Noise framework and is materially better than the launch build — but the P2 spec's position stands unchanged: study the transport, do not ship the crypto.
What it proves. BitChat is the strongest available evidence that our transport assumptions are viable at consumer scale: 10 000 TestFlight slots exhausted within hours, real use during the Madagascar and Nepal protests in September 2025, and functional background BLE mesh relaying on both mobile platforms. That last point matters more than it appears — background BLE on iOS is the single hardest constraint in our iOS BLE deep dive, and BitChat shipping it is an existence proof.
Head to Head
Routing discipline
who relays? cost per delivered packet self-organising?
Meshtastic everyone ~n transmissions yes — fully
MeshCore repeaters only ~path length no — needs sited repeaters
BitChat every phone ~n, damped by density yes — fully
Meshtastic and BitChat solve broadcast storms with the same idea reached independently — delay your rebroadcast by an amount derived from how well-placed you appear to be, and stay quiet if someone else already did it. Meshtastic measures placement by SNR; BitChat measures it by neighbour count. MeshCore avoids the problem structurally instead, by forbidding most nodes from relaying at all.
For our design the interesting observation is that all three converge on "not every node should relay equally" — which is the same conclusion our own architecture reaches with the WiFi relay and BLE dead drop prototypes. MeshCore's role taxonomy is the most explicit statement of it, and its room server is functionally our community relay: infrastructure that holds ciphertext for absent members without being trusted with plaintext.
Cryptography
| Confidentiality | Integrity | Forward secrecy | Authentication | |
|---|---|---|---|---|
| Meshtastic | AES-256-CTR (PSK) / curve25519 PKC for DMs | None on channel messages | No | Weak — MAC-derived node IDs |
| MeshCore | AES-128-ECB, zero-padded | 2-byte truncated HMAC | No | Ed25519-signed adverts |
| BitChat | ChaCha20-Poly1305 via Noise XX |
AEAD tag | Yes (sessions) | Mutual, in-handshake — but a disclosed flaw in the trust-pinning UX |
BitChat is the only one of the three whose live-session cryptography we would consider sound enough to reason about; both radio stacks fail closed-world assumptions that our threat model takes as given. This is unsurprising — LoRa's airtime budget punishes every additional byte, and a ratchet handshake is expensive under EU duty-cycle limits, which is exactly why P7 already defers ratcheting.
Metadata exposure
Ranked from most to least leaky, judged by what a passive observer with commodity hardware learns:
- Meshtastic — cleartext header with 4-byte node ID, hop count, and routing state on every packet, plus position and telemetry broadcasts by default. Long-term observation yields a node-to-location map and a co-presence graph.
- MeshCore — 1-byte node hashes in the path field leak less per packet, but adverts carry full public keys, and the accumulated path reveals network topology directly. Static keys mean identity is permanent.
- BitChat — ephemeral 8-byte sender IDs, no persistent account identifier, a fresh identity per geohash area, and no long-lived on-air ID. Still linkable through BLE MAC rotation behaviour and timing, but structurally the best of the three.
None reaches the standard set in our anonymity lifecycle analysis. Meshtastic and MeshCore both fail L1 (identity) and L3 (social graph) by construction, because flood routing and path learning both need a stable on-air identifier to suppress duplicates.
Trust establishment — where all three diverge from us
This is the sharpest gap, and it is not a bug in any of them:
- Meshtastic — anyone with the channel key joins. Keys are shared as URLs or QR codes, out of band and freely copyable.
- MeshCore — contacts are added by receiving a signed advert over the air. Proximity introduces you, but "in radio range" is kilometres, not arm's length.
- BitChat — any nearby device joins the mesh automatically; that openness is the design goal, and it is what makes it work in a protest crowd.
Our physical-first requirement — a contact exists only after an in-person NFC or QR exchange — is satisfied by none of them. That constraint remains ours to implement, and it is the single largest reason none of these three can be adopted wholesale rather than borrowed from.
Post-quantum readiness
All three use classical X25519/Ed25519 exclusively. None has a hybrid PQ path. Of the three, MeshCore is the hardest to retrofit: PQ key material would not fit its airtime budget, and its AES-ECB and 2-byte-MAC construction would need replacing regardless. Our hybrid classical + PQ goal stays a differentiator, and it argues for keeping our crypto envelope strictly independent of the transport, exactly as P7 specifies.
Fit Against Our Research Scope
Scored against the six criteria in our research scope:
| Criterion | Meshtastic | MeshCore | BitChat |
|---|---|---|---|
| Physical-first trust | ✗ channel key is copyable | ✗ over-the-air adverts | ✗ open join by design |
| Proximity discovery | ~ km-scale, not proximity | ~ km-scale, not proximity | ✓ BLE range is genuine proximity |
| Offline-first | ✓ no infrastructure at all | ✓ plus room-server catch-up | ✓ BLE mesh primary, internet opt-in |
| Structural privacy | ✗ cleartext header, position broadcasts | ✗ topology in path field, static keys | ~ ephemeral IDs, relays see ciphertext only |
| Anonymity by default | ✗ stable node ID required | ✗ permanent keypair | ✓ no accounts, per-area identity |
| Post-quantum ready | ✗ | ✗ | ✗ |
BitChat is closest to our goals and furthest from production-trustworthy. The two radio stacks are the reverse: dependable transports for hardware we would otherwise have to bring up ourselves, with security properties we must assume nothing from.
What We Take From Each
From MeshCore — the role taxonomy and path learning.
- Adopt the concept of enforced role separation in our architecture vocabulary. "Companion nodes never relay" is a one-line policy that removes an entire class of routing pathology, and it maps directly onto our existing split between user phones and dedicated relay hardware (P5, P6).
- Its room server validates the community-relay model in P5: store-and-forward infrastructure that a group sites deliberately, holding content it cannot read.
- Flood-then-direct path learning is worth measuring against managed flooding in P7's airtime budget. If the saving holds under our envelope sizes, it changes the duty-cycle maths materially.
- Treat its cryptography as a cautionary example, not a component. A 2-byte MAC and ECB mode are what "small enough to fit on air" produces when the envelope is not designed for confidentiality — and they are why our envelope must never depend on the transport's.
From Meshtastic — the ecosystem and the honesty.
- Keep it as P7's baseline. The protobuf BLE API, flasher, Python bindings, community range data, and multi-platform apps are worth more to a research prototype than a routing improvement.
- Its documentation states its own gaps — no PFS, no channel-message integrity, trivial impersonation with the channel key. That candour is exactly the standard we should hold our own specs to.
- Its >40-node throttling algorithm is a concrete data point on when a flooded mesh saturates. Our P7 duty-cycle budget should cite it rather than re-derive it.
From BitChat — the BLE transport parameters and the adoption evidence.
- Its density-adaptive flood parameters are directly reusable in P2: TTL 7 at origin capped to 5 in dense graphs, 10–220 ms jitter widening with neighbour count, and a 1000-entry / 5-minute LRU duplicate cache. These are field-tuned numbers on the exact transport P2 targets.
- Its fragmentation approach (~469-byte fragments, bounded concurrent reassembly, hard size cap) is a sane BLE MTU strategy and a defence against reassembly-based memory exhaustion — worth mirroring in P2's queue design.
- Noise
XXfor live sessions plus a one-way pattern for store-and-forward is the same shape our feed format needs. Its explicit acknowledgement that the offline path loses forward secrecy is the honest framing of a trade-off we also face in P6. - Background BLE mesh working on iOS is an existence proof against the pessimism in our iOS BLE analysis — worth a targeted teardown of how they hold the connection alive.
- Its security history is the argument for our audit-readiness posture: shipping a mesh messenger before the identity-authentication path is reviewed produces an impersonation vulnerability, publicly, within weeks.
Consequences for Prototype 7
P7 currently specifies Meshtastic firmware as the transport under our own encrypted envelope. This comparison does not overturn that, and adds three refinements:
- Keep Meshtastic as the baseline. Ecosystem maturity and stable governance outweigh MeshCore's airtime efficiency at this research stage.
- Add MeshCore as a measured alternative, not a swap. A side-by-side airtime and delivery-latency measurement over the same envelope sizes and the same duty-cycle regime would tell us whether path learning changes P7's bandwidth conclusions. If it does, the migration cost is bounded, because the security boundary is already ours.
- Record the governance risk explicitly. The MeshCore trademark dispute is unresolved. If P7 takes any MeshCore dependency, pin the commit and the fork, and note that the canonical repository may move.
Neither radio stack changes the Gap 5 finding: an on-air identifier stable enough for duplicate suppression is a structural requirement of both flood routing and path learning. MeshCore's 1-byte hash is a smaller leak than Meshtastic's 4-byte node ID, not the absence of one.
Open Questions
- Does MeshCore's flood-then-direct routing survive the mobility our use case implies? Path learning assumes a topology stable enough for a learned path to remain valid; people moving between valleys may invalidate paths faster than discovery can rebuild them.
- What is the actual airtime saving for our envelope sizes, in a duty-cycle-limited region, at realistic node counts — 5, 20, 50 nodes?
- Can a room server hold our feed format entries unmodified, or does its BBS post model impose a schema we would have to work around?
- How does BitChat keep BLE mesh relaying alive in the iOS background, and how much of that is transferable to a physical-first design where peers are a closed set rather than any nearby device?
- Is there an on-air identifier scheme that satisfies duplicate suppression without providing a long-term correlation handle — rotating hashes with a shared epoch schedule, for example — and can it be implemented without forking firmware?
- Does any of the three have a credible path to hybrid post-quantum key exchange within LoRa or BLE payload budgets, or is that necessarily our own layer?
Sources
- MeshCore vs Meshtastic — Austin Mesh · OpenELAB comparison
- Meshtastic — Mesh Broadcast Algorithm · Meshtastic — Encryption · LoRa configuration / hop limits
- MeshCore (GitHub, meshcore-dev) · MeshCore network protocol · MeshCore protocol specification (reverse-engineered)
- A Hitchhiker's Guide to MeshCore Cryptography — Jack Kingsman — cipher mode, MAC truncation, key format
- Help Us Save MeshCore — MeshCore blog, 4 July 2026 · MeshCore — Wikipedia
- bitchat (GitHub) · bitchat-android · bitchat whitepaper
- Building secure messaging is hard: a nuanced take on the Bitchat security debate — Trail of Bits, 18 July 2025
- Bitchat, Bluetooth mesh networks and internet shutdowns — Bloomsbury Intelligence and Security Institute
- BitChat — Wikipedia
Related pages: Existing Protocols · Market Research · Implementation Options · Spec: LoRa Radio Mesh · Spec: BLE Messenger · Anonymity Coverage Across Prototypes