Home/Security & privacy

What a carrier can see

Sealed, unaddressed, and nobody’s to filter

Worth being precise about, because it’s the part that’s easy to hand-wave. Here is exactly what a stranger carrying your message holds, and exactly what they can do with it.

Sealed end to end

Every message is encrypted to the recipient before it leaves your device — a carried message with X25519, HKDF-SHA256 and ChaCha20-Poly1305, a message sent the MeshCore way with MeshCore’s own encryption. No plaintext path exists anywhere in the system — not as a fallback, not for compatibility, not for an unknown contact.

No cryptographic primitive is ever invented. Standard, widely used primitives only.

No readable destination on the wire — the MeshDTN way

This is the one that surprises people. A carrier holding your message has no field to read that says who it’s for. They can’t address it, can’t filter it, can’t decide they dislike where it’s going — because there is no way for them to know. A message sent the MeshCore way does carry a destination hash, as every MeshCore message does — the difference, side by side.

The recipient is identified by an 8-byte tag derived from a key only the two of you hold and a fresh nonce on every message. Nobody else can recognize it, and no two messages carry the same value.

Your choice, per message

The MeshCore way and the MeshDTN way are not equally private

Every contact is set to MeshCore, Auto or MeshDTN, and any single message can override it. Auto is the default. The difference that matters is what goes on the air.

SentThe MeshCore wayThe MeshDTN way
On the wireA stock MeshCore text message, flood or directMeshDTN carry frames, handed on only between MeshDTN nodes that have switched relaying on
Who can move itAny MeshCore repeater, room server or nodeOnly MeshDTN carriers and stations
Destination on the airA destination hash, visible to every hopNone a carrier can read — an 8-byte tag, different every message
Can a hop log itYes, as any repeater can todayNo
Recipient absentFails after retries, and you are toldWaits, up to ninety days
Delivery receiptMeshCore’s acknowledgementA MeshDTN delivery receipt

Scroll the table sideways to see every column.

A MeshCore-way message is exactly as private as MeshCore

No more. Every hop can see which contact it is for. Auto sends the MeshCore way first, and only a message the radio cannot deliver is carried.

A MeshDTN-way message has no readable destination on the air

Nothing a hop can read says who it is for. The app shows which way each message went, on the message itself, so you never have to guess.

Precisely

What a node carrying your message can and cannot do

It CAN see

  • That it holds a blob of ciphertext of a certain size
  • A short opaque identifier for it
  • When it expires
  • How many phones have already carried it

It CANNOT see

  • The contents
  • Who it’s from
  • Who it’s for — the tag changes on every message
  • Whether it’s for them, until they try their own key

It CANNOT do

  • Select what it carries
  • Log who it met
  • Reach a hub, because none exists

Invariant one — no selection

No allowlist, no blocklist, no operator filter, no content policy, no priority class. This is a written invariant with a test behind it — the property is free today because a carrier can’t read anything, and the only way to lose it is for somebody to add a knob believing it’s a feature.

Invariant two — no encounter log

Recording message identifiers or peer identities against timestamps builds an encounter history — the exact object the design exists to prevent. Airtime, byte counts, signal strength and durations are measurements. An identifier is somebody else’s metadata.

Messaging

What that buys you, message by message

Delivery receipts that mean something

A kill record is authorized by a cryptographic commitment reveal. Only someone who could genuinely open the message can mint a DELIVERED; only the sender can mint a CANCEL or a SUPERSEDES. A carrier verifies it in constant time before acting on it.

Cancel and supersede

Change your mind, or replace a message with a corrected version, and the network stops carrying the old one.

Long messages, never truncated

Fragmentation splits a message across as many radio frames as it takes. Fragments arrive out of order, days apart, from different carriers, and the message still opens whole. If it can’t be sent, you’re told — it is never silently shortened.

Retention that doesn’t throw messages away

Ninety days, with eviction rules that never discard payloads addressed to your own contacts before anything else, and expiry suspended entirely when the clock can’t be trusted.

Eighteen languages

Localized throughout, including failure messages — because a Spanish-speaking operator at the foot of a pole should not get an English error.

You cannot message a stranger

And the app tells you that at the moment you try — not after a failure.

Contacts and trust

How you know someone is a signed property, not a guess

Contacts persist like a real messenger, not like a radio scanner. Add someone once and they stay. How you came to know them is recorded on the contact itself.

Tier 0
Heard on the air
Tier 1
Exchanged keys in person over the network
Tier 2
Verified out of band, by QR scan

Broadcast channels

We call it a broadcast channel, and not “a group chat”, because that’s what it is

A broadcast channel is a shared symmetric key distributed out of band — scan one QR at a staging area and everybody in the group can read everything sent to it.

Every member can decrypt everything ever sent to the channel, including traffic from before they joined. There’s no forward secrecy and we don’t claim any. The UI shows you plainly which kind of conversation you’re in, because a broadcast channel and a private two-person message have security properties that are not comparable, and presenting them identically would be a lie.

Group messages expire on time rather than on delivery — because no node can know how many members a channel has, and a “delivered” from the first member to open a message must never stop the rest of the group receiving it.

Groups make the budget better, not worse

One payload reaches many recipients at one carry slot. A solar station is the ideal node for holding channel traffic — drop stations across a zone and responders passing through pick up everything left for the group and drop off everything they’re carrying.

The disaster-response pattern

The regulatory envelope

A wrong radio setting produces silence, not an error

The radio does not choose its own parameters and neither does the app. Frequency, spreading factor, bandwidth and coding rate are fixed in the firmware build, inherited unchanged from the project MeshDTN was forked from. A station refuses every attempt to change them, and refuses each one by name so an operator learns the station declined rather than concluding the firmware is old.

There is no geolocation in any of this. The app does not read your country, your mobile network, or your position in order to decide what the radio may do — so choosing a build that is legal where you are is your decision, not something the software makes for you.

The reason to care is reliability as much as compliance: a wrong radio setting produces silence, and silence is indistinguishable from “nobody is around.” And your region never enters a frame.

Your responsibility

Operating a radio lawfully depends on where you are

MeshDTN runs on license-free bands, but regulations vary by country and are yours to observe. NOTICE.md sets out the relevant regulatory facts with citations and draws no conclusions. Read it before you transmit.

Deliberately absent

The internet

We considered linking stations over IP and rejected it. Payloads would stay sealed, but a central service would see every station, every identifier and every timestamp in one place — and the first station to receive a message got it from someone standing nearby. That reassembles a movement trace of senders in the one component with a complete view.

It’s also a one-way door: you can add a hub later, you can’t credibly remove one. And if an internet path exists it becomes the default path, after which the store-and-carry network rots quietly and fails on the day it’s needed.

No server. No account. No cellular carrier. No internet.

There is no MeshDTN company that can go out of business and take your network with it.

What we claim, and what we do not

Nothing in MeshDTN has been audited

No security property in this project has been independently reviewed, and the Charter forbids claiming otherwise. Until that review happens, every security property described anywhere on this site is a design target, not an assurance.

MeshDTN invents no cryptography. A carried message is sealed with X25519, HKDF-SHA256 and ChaCha20-Poly1305, with an HMAC-SHA256 recipient tag, every primitive from a published library. There is no forward secrecy: the key between two contacts does not rotate. That is a deliberate trade for simplicity. Every choice is written down in the Protocol, field by field, so it can be checked rather than taken on trust.

A library’s assurance covers the library, not the way this project combines it. What may be claimed is the construction; what may not be claimed is the scrutiny.

Independent cryptographic review is where outside help is worth the most. The primitives are standard and the specification is public, which makes review tractable. If you do this work professionally, we’d welcome your eyes on it.

They’re doing you a favor they can’t inspect.

Read the frame layouts field by field, or start carrying.