BLE Notfall-Mesh ← Startseite / Home

Technische Übersicht des Protokolls

BLE Notfall-Mesh · Kompaktfassung · English version below

Dieses Dokument beschreibt in Grundzügen, wie BLE Notfall-Mesh technisch arbeitet — die Prinzipien, nicht die Bauanleitung. Die Sicherheit der App beruht bewusst nicht auf Geheimhaltung des Verfahrens, sondern auf etablierter, öffentlich geprüfter Kryptografie.

Grundidee

Es gibt keinen Server. Jedes Gerät ist gleichzeitig Sender, Empfänger und Brücke. Nachrichten springen über Bluetooth Low Energy (BLE) von Gerät zu Gerät, bis sie ihr Ziel erreichen. Ein Gerät, das gerade keinen Nachbarn hat, hält Pakete vor und gibt sie beim nächsten Treffen weiter. So entsteht Reichweite aus vielen kurzen Sprüngen.

Kryptografische Bausteine

Es kommen ausschließlich standardisierte, breit analysierte Verfahren zum Einsatz:

BausteinVerfahrenWofür
SignaturenEd25519Beweist, von wem eine Nachricht stammt (Echtheit & Unverfälschtheit)
SchlüsseltauschX25519Gemeinsamer Schlüssel für Direktnachrichten, pro Nachricht frisch
VerschlüsselungChaCha20-Poly1305Inhalt verschlüsseln und gegen Veränderung sichern (AEAD)
HashBLAKE2bFingerabdrücke, Paket-IDs, Kanalkennungen
Passwort → SchlüsselArgon2idKanalschlüssel aus Name + Passwort; Schutz verschlüsselter Sicherungen
SchlüsselableitungHKDF (SHA-256)Sitzungs- und Nachrichtenschlüssel ableiten; saubere Domänentrennung
RuheverschlüsselungAES-256-GCM (Android-Schlüsselspeicher)Sensible Felder auf dem Gerät verschlüsseln: Identität, Kanalschlüssel und -passwörter, Nachrichtentexte, Kontaktnotizen

Jede Identität besteht aus zwei Schlüsselpaaren (Ed25519 zum Signieren, X25519 zum Verschlüsseln). Sie entstehen beim ersten Start auf dem Gerät, werden zusätzlich im Android-Schlüsselspeicher gesichert und verlassen das Gerät nie. Ihr Fingerabdruck (die „Sicherheitsnummer") lässt sich mit einem Gegenüber vergleichen, um einen Kontakt zweifelsfrei zu bestätigen.

Auf dem Gerät gespeichert (Ruheverschlüsselung)

Die empfindlichsten Daten liegen auf dem Gerät nicht im Klartext: die privaten Identitätsschlüssel, die Kanalschlüssel samt Passwörtern, die Nachrichtentexte sowie deine Kontaktnotizen und Feldwerte werden mit einem gerätegebundenen Schlüssel aus dem Android-Schlüsselspeicher feldverschlüsselt. Eine erbeutete Datenbankdatei gibt daraus weder Inhalte noch Schlüssel preis. Metadaten (Zeitstempel, Paket-IDs, Absenderkennung) bleiben offen, und die Datenbank selbst bleibt entsperrt, damit ein gesperrtes Gerät weiter weiterleitet. Gegen ein laufendes, entsperrtes Gerät hilft das nicht — dafür gibt es App-Sperre, optionale Auto-Löschung nach mehreren Fehlversuchen und Panik-Löschung.

Zwei Wege: Direktnachricht und Kanal

Direktnachricht („Sealed Sender")

In einem Netz, in dem jedes Gerät jedes Paket weiterträgt, darf nirgends im Klartext stehen, für wen ein Paket ist. Deshalb:

Ein weiterleitendes Gerät sieht dadurch weder Inhalt noch Absender noch Empfänger — nur ein verschlüsseltes Bündel, das es blind weiterträgt.

Kanäle

Ein Kanal ist durch einen Namen und ein Passwort definiert. Daraus wird lokal per Argon2id ein gemeinsamer Schlüssel abgeleitet; auf dem Gerät wird nichts registriert und niemand verwaltet Mitglieder. Wer Name und Passwort kennt, kann mitlesen und schreiben. Einladungen bestehen aus Name + Passwort (als Text oder QR-Code) — es gibt keine Instanz, bei der man sie hinterlegen könnte. Ein Kanal kann auch offen sein (ohne Passwort): dann entsteht der Schlüssel aus dem Namen und einem festen, öffentlich bekannten Passwort — jeder mit dem Namen liest mit. Der eingebaute Notruf-Kanal ist so ein offener Kanal, damit sich Fremde im Ernstfall ohne Vorabsprache erreichen können; offene Kanäle sind ausdrücklich nicht vertraulich.

Fluten und Vorhalten (Store-and-Forward)

Jedes Gerät bietet Nachbarn eine Liste der Paket-Kennungen an, die es hat; der Nachbar fordert nur an, was ihm fehlt. Jede Paket-ID ist der Hash des Pakets selbst (inhaltsadressiert), sodass dasselbe Paket nie doppelt gespeichert oder endlos im Kreis geschickt wird. Fremde, unlesbare Pakete werden eine begrenzte Zeit vorgehalten (einstellbar 2–72 Stunden) und dann verworfen, ebenso bei vollem Speicher — Notrufe bleiben dabei am längsten erhalten.

Wovor das Verfahren schützt

Grenzen

Kein System schützt vor allem. Diese Punkte lassen sich technisch nicht vermeiden — deshalb stehen sie hier.

Offline-Karten

Kartenpakete sind .mbtiles-Dateien — SQLite-Datenbanken mit Kacheln. Verwendet werden Vektorkacheln: Statt fertiger Bilder enthalten sie Geometrien, die auf dem Gerät gezeichnet werden. Das ergibt Straßennamen, die dem Straßenverlauf folgen, saubere Beschriftungsverteilung und bei jeder Zoomstufe scharfe Darstellung.

Gezeichnet wird mit MapLibre. Weil diese Bibliothek Kacheln nur über URLs lädt, läuft in der App ein Server, der ausschließlich an 127.0.0.1 gebunden ist: Er liefert Kacheln aus der lokalen Datei, den Stil und die Schriften. Diese Verbindungen verlassen das Gerät nicht. Die Netzwerkregeln der App verbieten unverschlüsselte Verbindungen grundsätzlich und lassen sie nur für diese Rückschleife zu.

Das Herunterladen eines Kartenpakets ist der einzige echte Netzzugriff der App. Er geschieht nur auf ausdrückliche Aktion des Nutzers, läuft über HTTPS und nimmt nach einem Abbruch per Bereichsanfrage die Übertragung wieder auf. Alternativ importiert man eine Datei, die außerhalb der App geladen wurde.

Erzeugt werden die Pakete mit planetiler aus OpenStreetMap-Daten (ODbL, Kachelschema OpenMapTiles, CC-BY). Enthalten sind Straßen, Straßennamen, Gewässer, Bahnlinien, Ortsnamen und Grenzen bis Zoomstufe 14; Gebäude, Geschäfte und Landbedeckung werden weggelassen, was die Pakete etwa halbiert. Sie müssen im internen App-Speicher liegen: Auf dem FUSE-Speicher unter /sdcard fehlt das Dateisperren, das SQLite zum Öffnen braucht — die App kopiert importierte Pakete deshalb dorthin. Ältere Raster-Pakete bleiben weiterhin lesbar.

Offen und prüfbar

Bei Fragen zur Technik: support@stahldata.de.


Technical Protocol Overview

BLE Notfall-Mesh · Compact edition

This document outlines how BLE Notfall-Mesh works technically — the principles, not a build manual. The app's security deliberately does not rely on keeping the method secret, but on established, publicly analysed cryptography.

Core idea

There is no server. Every device is sender, receiver and bridge at once. Messages hop from device to device over Bluetooth Low Energy (BLE) until they reach their destination. A device with no neighbour in range holds packets and passes them on at the next encounter. Range is built from many short hops.

Cryptographic building blocks

Only standardised, widely analysed primitives are used:

BlockPrimitivePurpose
SignaturesEd25519Proves who a message is from (authenticity & integrity)
Key exchangeX25519Shared key for direct messages, fresh for each message
EncryptionChaCha20-Poly1305Encrypts content and protects it from tampering (AEAD)
HashBLAKE2bFingerprints, packet IDs, channel identifiers
Password → keyArgon2idChannel key from name + password; protects encrypted backups
Key derivationHKDF (SHA-256)Derives session and per-message keys; clean domain separation
Encryption at restAES-256-GCM (Android keystore)Encrypts sensitive fields on the device: identity, channel keys and passwords, message texts, contact notes

Each identity consists of two key pairs (Ed25519 for signing, X25519 for encryption). They are created on the device at first start, additionally protected by the Android keystore, and never leave the device. Their fingerprint (the “safety number”) can be compared with the other person to confirm a contact beyond doubt.

Stored on the device (encryption at rest)

The most sensitive data does not sit in plaintext on the device: the private identity keys, the channel keys with their passwords, the message texts and your contact notes and field values are field-encrypted with a device-bound key from the Android keystore. A captured database file yields neither contents nor keys. Metadata (timestamps, packet IDs, sender id) stays open, and the database itself stays unlocked so a locked device keeps relaying. This does not help against a running, unlocked device — for that there are the app lock, the optional auto-erase after several wrong attempts, and the panic erase.

Two paths: direct message and channel

Direct message (“sealed sender”)

In a network where every device relays every packet, the recipient must never appear in the clear. Therefore:

A relaying device therefore sees neither content nor sender nor recipient — only an encrypted bundle it carries onward blindly.

Channels

A channel is defined by a name and a password. A shared key is derived from them locally via Argon2id; nothing is registered on any device and no one manages members. Anyone who knows the name and password can read and write. Invitations are just name + password (as text or a QR code) — there is nowhere to lodge them. A channel can also be open (no password): the key is then derived from the name and a fixed, publicly known password, so anyone with the name reads along. The built-in emergency channel is such an open channel, so strangers can reach each other with no prior arrangement; open channels are explicitly not confidential.

Flooding and store-and-forward

Each device offers neighbours a list of the packet IDs it holds; the neighbour requests only what it is missing. Every packet ID is the hash of the packet itself (content-addressed), so the same packet is never stored twice or sent around in circles. Foreign, unreadable packets are held for a limited time (configurable 2–72 hours) and then dropped, as they are when storage fills — emergency calls are kept the longest.

What the design protects

Limits

No system protects against everything. These points cannot be avoided technically — which is why they are listed here.

Offline maps

Map packages are .mbtiles files — SQLite databases holding tiles. They contain vector tiles: instead of ready-made images they hold geometry that is drawn on the device. This yields street names following the course of the road, proper label placement and a sharp picture at every zoom level.

Rendering is done by MapLibre. Since that library only loads tiles via URLs, the app runs a server bound exclusively to 127.0.0.1: it serves tiles from the local file, the style and the fonts. These connections never leave the device. The app's network rules forbid cleartext connections in general and permit them only for this loopback.

Downloading a map package is the app's only real network access. It happens on explicit user action, over HTTPS, and resumes via range requests after an interruption. Alternatively a file fetched outside the app can be imported.

Packages are produced with planetiler from OpenStreetMap data (ODbL, OpenMapTiles schema, CC-BY). They contain roads, street names, water, railways, place names and boundaries up to zoom level 14; buildings, shops and land cover are omitted, which roughly halves their size. They must live in internal app storage: the FUSE storage under /sdcard lacks the file locking SQLite needs — which is why the app copies imported packages there. Older raster packages remain readable.

Open and auditable

Questions about the technology: support@stahldata.de.