Four Ways to Message Off-Grid: Briar, Knit, and bitchat Compared

There's a small cluster of open-source apps that promise to let you message people without cell service, wifi, or a server anyone controls. They bounce encrypted messages phone-to-phone over Bluetooth, or hold onto them in a dead-drop until someone can pick them up. I'd seen four of them mentioned around enough times that I wanted to actually read the code instead of the marketing copy: Briar, Knit, and bitchat, which ships as two sibling implementations. One is Swift for iOS/macOS, one is Kotlin for Android, and they share a wire protocol but not always the same behavior.

They're all solving the same problem: off-grid messaging without central infrastructure. But the actual engineering underneath is surprisingly different. Here's what I found going through background execution, offline delivery, mesh transport, and crypto in each.

Quick reference #

BriarKnitbitchat (iOS)bitchat-android
Transport modelPairwise, trust-graph + TorFlood mesh (BLE + Wi-Fi Aware)Flood mesh (BLE only)Flood mesh (BLE + Wi-Fi Aware)
Offline deliverySelf-hosted Tor "mailbox" dead-dropDB-backed store + anti-entropy digest syncSender outbox + physical/virtual couriers + NostrIn-memory cache + Nostr fallback
HandshakeBQP (Curve25519 DH + commitment)X3DH-style (3x X25519 DH)Noise XXNoise XX
Forward secrecyPer-transport-time-period key rotationPer-epoch ratchet (~200 msgs/24h)Per-message (live), weaker offlinePer-message (live)
PlatformAndroid + desktop headlessAndroid onlyiOS/macOSAndroid

Off-grid doesn't have to mean mesh #

Worth getting this out of the way first, since it shapes everything else. These four split into two transport models for the same underlying goal.

Knit and both bitchats are genuine flood/relay meshes. Your phone forwards other people's traffic, hopping messages across strangers' radios until they reach their target. Briar isn't built that way. Every connection it makes, whether Tor, Bluetooth, local wifi, or even a USB drive, goes directly to a specific contact you've already added, and nothing relays through a stranger's device. It uses Tor for the reach a radio mesh would otherwise get from hopping, plus a gossip mechanism for forum and group content that spreads only across your existing mutual contacts. Both are legitimate answers to off-grid messaging without a server; they just make opposite trade-offs between reaching strangers and keeping the trust circle small.

Staying alive in the background #

Nobody's found a loophole around Android's rules here. Briar, Knit, and bitchat-android all converge on the same shape: a foreground Service, a persistent low-priority notification, a boot receiver, and a prompt asking the user to exempt the app from battery optimization. The differentiation is in how smart each one is about when to actually burn radio power scanning.

bitchat on iOS doesn't get any of these levers. Apple's background BLE rules are stricter across the board, so the whole story is CoreBluetooth's built-in state-restoration API (CBCentralManagerOptionRestoreIdentifierKey and friends), which lets the app rebuild its Bluetooth link state after iOS suspends and relaunches it in the background. There's no Android-style fine-grained scheduling available to reach for.

Reaching someone who isn't there right now #

This is where the four diverge the most. Two mechanisms are worth sitting with in particular: Briar's mailbox and bitchat's courier system.

A Briar mailbox is small self-hosted infrastructure, like a spare phone or a cheap VPS, running as a Tor hidden service that a user sets up themselves as a drop-box contacts can leave messages in. The implementation is neat: it's literally just another SimplexPlugin, reusing the same FilePlugin base class as Briar's removable-USB-drive transport. Each contact gets an isolated inbox/outbox folder pair and a private auth token that grants folder access only, never decrypt or sign capability. So the mailbox operator sees rough timing and blob sizes and nothing else. It can go offline and stall your delivery, but it can't read or forge anything.

bitchat's courier mechanism solves the same "recipient isn't reachable right now" problem in a completely different way. Any nearby phone running bitchat can carry a sealed, opaque envelope on behalf of someone it might later run into, with a spray-and-wait copy budget (starting at up to 8 copies, halved on each handoff) that substitutes redundancy across strangers for Briar's one-chosen-relay reliability. It's a genuinely inventive idea: it can deliver between two devices that were never online at the same time, with zero setup required. But the project's own docs (docs/PEER-ID-ROTATION.md) admit a real flaw. The day-rotating tag couriers use to figure out who an envelope is for is an HMAC over the recipient's public key, and that key gets broadcast in cleartext in every announce packet. So any passive listener, not just an actual courier, can precompute and correlate a peer's tags across days. Content integrity in both systems is equally solid; a tampered message just fails to decrypt in either design, with no silent corruption. The real difference is that Briar's relay is infrastructure you specifically chose, while bitchat's is an anonymous population of strangers' phones, and that choice is exactly what determines how contained the metadata leakage stays.

Durability varies a lot too. Knit's forward_store (Room + SQLCipher) and bitchat-iOS's outbox both persist to encrypted disk and survive a restart. bitchat-android's StoreForwardManager currently caches everything in plain ConcurrentHashMaps, so force-closing the app wipes out whatever was queued. Knit's redelivery mechanism is the most sophisticated of the four: instead of re-flooding cached messages at a newly-seen neighbor, it exchanges a short digest of held message IDs and only sends the delta. That's an actual anti-entropy sync rather than a blind re-push, and it means a mesh that's already converged does close to zero extra work.

Would any of this hold up in a crowd? #

None of the four projects publish load-test numbers, so take this section as reasoning from the code and known radio constraints, not a measured result.

The real ceiling is almost certainly Bluetooth's connection-count limit, not any relay algorithm. A BLE central can only hold a handful of GATT connections open at once (bitchat-android's code caps it explicitly at 8), so a crowd of a few hundred phones fragments into many small, overlapping clusters no matter how clever the software is. That's the actual reason multi-hop relay exists at all.

At small scale, a handful to a few dozen devices in one cluster, Knit, bitchat, and bitchat-android should all behave comparably. There isn't enough redundant chatter yet for their different rebroadcast-suppression strategies to matter. They diverge more in the tens-to-hundreds range, a regime all three explicitly designed for. bitchat-android's own decay curve names both a ≤10 and a >100 peer threshold directly in the code.

Wi-Fi Aware (used by Knit and bitchat-android, not iOS) helps throughput for a given exchange, which is useful for attachments. But its data-path negotiation is one-active-exchange-at-a-time in Knit's implementation, so it doesn't raise how many simultaneous peers a device usefully meshes with. Whichever relay algorithm wins on paper, my bet is that the actual bottleneck at real crowd scale is BLE connection fragmentation, a limit common to all three, well before any of these suppression strategies start mattering.

Briar sidesteps this whole class of problem, since it was never sharing a radio channel among strangers in the first place. Its scaling limits are the number of contacts one device polls and how much load a mailbox server can take, both ordinary infrastructure problems rather than radio-physics ones.

Security, briefly #

All four get the primitives right: modern AEAD ciphers, X25519/Curve25519 agreement, Ed25519 signatures, nothing home-rolled. Where they differ is forward-secrecy granularity, which turns out to be a spectrum shaped by each project's delivery model rather than a simple better/worse ranking.

Every one of those forward-secrecy bullets is describing private messages, and it's worth being explicit that this is a distinct question from whether a message is encrypted at all. I've since gone and built a wire-compatible bitchat client from scratch (reverse-engineering the actual binary protocol byte-by-byte, not the whitepaper prose), and one thing that surprised me: bitchat's default experience, the public mesh chat every nearby stranger sees by just opening the app, is completely unencrypted. The wire payload for a public message or announce packet is raw UTF-8 with no cipher applied at all; the only cryptographic ingredient is an Ed25519 signature over the packet, which authenticates who sent it, not who can read it. Anyone with a BLE radio in listening range can read every public message and every announce (nickname, static Noise/signing public keys) without decrypting anything, on both iOS and Android. None of the forward-secrecy machinery above touches this path at all, it only ever applies once you drop into a 1:1 DM and a Noise XX handshake completes. That's a reasonable design choice for a public local chat, but it's easy to read "Noise XX, per-message forward secrecy" in a comparison table and assume it covers the whole app rather than just its private-messaging half.

Two more things are worth flagging, since they're the kind of detail you only find by reading code instead of README files. First, bitchat's own whitepaper is refreshingly blunt that "metadata is the weakest part of this design, and the peer ID does not help." The sender ID is derived from a static key hash and never rotates, so a passive listener can track a device across locations over time; there's a drafted fix with test vectors that simply isn't shipped yet. Second, bitchat-android's README claims Argon2id for channel-password derivation, but the actual code uses PBKDF2-HMAC-SHA256 at 100k iterations. That correctly matches iOS, it just doesn't match what the README says it does. Worth checking the code, not the marketing, before trusting any specific claim from a project like this.

A third thing, also only visible from the code: bitchat's Nostr fallback path (used to reach a mutually-favorited contact over the internet when there's no BLE path between you) labels its encryption "NIP-44 v2" on the wire, but it isn't the standard NIP-44 that the rest of the Nostr ecosystem implements. The published NIP-44 spec calls for ChaCha20 plus a separate HMAC-SHA256 authentication step, with the plaintext padded into fixed length buckets specifically to stop message-length fingerprinting. bitchat-android's implementation (NostrCrypto.kt) instead runs XChaCha20-Poly1305 as a single AEAD call, with no plaintext padding whatsoever, and its own code comments admit it: "Match iOS: derive HKDF input from the compressed shared point," describing a key-derivation step that isn't in the public spec either. Functionally this still gets you confidentiality and authenticity between two bitchat installs, but it means bitchat's Nostr DMs are opaque to (and unreadable by) any standard Nostr client, and they skip the length-hiding padding a spec-compliant NIP-44 implementation would apply. If part of the appeal of the Nostr fallback is "falls back to the wider Nostr network," that's not quite what's happening; it falls back to Nostr relays as a transport, but only other bitchat clients can actually read what gets sent.

Where that leaves things #

Briar is the most institutionally mature of the four. Dagger DI, a database migration chain running to nearly 50 versions, and reproducible Docker builds so published APKs can be verified against source all point the same way: it gets there by deliberately keeping its trust surface small, pairwise contacts only, no ad-hoc relay through strangers. Knit is the newest and, in some ways, the most cryptographically deliberate, with real thought put into the specific hard problem of combining forward secrecy with storage that has to evict old messages. bitchat's two versions are the most ambitious in scope. Physical message-carrying couriers are a genuinely novel idea, and they're paired with the most publicly candid self-assessment of the group, admitted weaknesses included. None of these are better or worse versions of the same app. They're four different, defensible answers to what off-grid messaging should trade away.

Published