‹ zurück zur App

Sicherheitsmodell

Was diese App schützt, wie sie es tut, und — genauso wichtig — wogegen sie nicht hilft. Wer eine Sicherheitszusage nicht überprüfen kann, hat keine.

Wie ein Konto entsteht

Es gibt keine Registrierung. Beim Anlegen erzeugt dein Browser zwei Schlüsselpaare auf der Kurve P-256: eines zum Signieren (ECDSA), eines für Schlüsselaustausch (ECDH). Deine Identität ist der SHA-256-Hash beider öffentlicher Schlüssel. Der Server erfährt nur diesen Hash und die öffentlichen Teile — nie einen privaten Schlüssel, nie ein Passwort.

Beim Verbinden schickt der Server eine Zufallszahl, die du signierst. Damit ist bewiesen, dass du den privaten Schlüssel hast. Ein Angreifer, der die Verbindung mitschneidet, kann daraus nichts wiederverwenden.

Die drei Stufen

cipher kennt drei Stufen mit drei verschiedenen Versprechen. Stufe 1 und 2 sind Bereiche, zwischen denen du wechselst; Stufe 3 ist eine Eigenschaft eines einzelnen Raums und in beiden Bereichen verfügbar.

StufeZugangWas bleibt
1 — Offen direkt, optional mit App-Passwort Identität und Verlauf, verschlüsselt auf diesem Gerät
2 — Verborgen PEM-Schlüsseldatei bei jedem Start eigener Verlauf in einem Tresor, der von außen wie Zufall aussieht
3 — Flüchtig keiner — ein Raum innerhalb Stufe 1 oder 2 nichts: kein Tresor, keine Warteschlange, kein Anrufeintrag

Der verborgene Bereich hat ein eigenes Konto mit eigenem Kontaktcode und eigener Verbindung. Für das Relay sind das zwei verschiedene Menschen.

Wo dein Schlüssel liegt

Der Schlüssel der Stufe 2 existiert in genau zwei Zuständen: im Arbeitsspeicher dieses Tabs, und in der PEM-Datei, die du selbst verwahrst — verschlüsselt mit PBKDF2-HMAC-SHA-256, 600 000 Iterationen, dann AES-256-GCM. Auf dem Gerät landet er nie.

Der Schlüssel der Stufe 1 muss bleiben, sonst wäre es keine normale App. Er liegt in Tresor A, verschlüsselt mit einem zufälligen Datenschlüssel. Dieser wiederum ist verpackt — entweder mit deinem App-Passwort (PBKDF2, 600 000 Runden), oder, wenn du keines setzt, mit einem Gerät-Schlüssel, der als extractable: false in der Datenbank liegt: benutzbar, aber nicht auslesbar.

Die App benutzt kein localStorage, sessionStorage, keine Cookies und keinen Service Worker. In IndexedDB liegen genau vier Objekte:

slots16 Byte Salt und 8 gleich große Schlüsselfächer
aTresor A — Stufe 1
bTresor B — Stufe 2
dkder Gerät-Schlüssel, nur ohne App-Passwort

slots und b gibt es ab dem allerersten Start, gefüllt mit Zufall. Dass sie da sind, beantwortet also nicht die Frage, ob dieses Gerät einen verborgenen Bereich hat.

Die Schlüsselfächer

Acht Fächer zu je 256 Byte, nach dem Vorbild von LUKS. Ein Fach kann den Datenschlüssel für Tresor B enthalten — dann öffnet es die PEM-Datei. Ein anderes kann eine Notfall-Markierung enthalten — dann öffnet es ein Passwort, ganz ohne Datei. Alle übrigen sind Zufall.

Der Klartext jedes Fachs ist ein Datensatz fester Länge, verschlüsselt mit AES-256-GCM. Alle acht sind damit exakt gleich lang, egal was drinsteht. Ein forensisches Abbild sieht 8 × 256 Byte Zufall und beantwortet keine Frage: nicht, ob ein verborgener Bereich existiert, nicht, ob ein Notfall-Passwort gesetzt ist, nicht, wie viele Schlüssel es gibt.

Beim Entsperren werden immer alle acht Fächer geprüft, und der Versuch dauert immer mindestens 1,2 Sekunden — Treffer, Notfall-Löschung und Fehlversuch sind an der Zeit nicht zu unterscheiden.

Bei der Meldung gilt das für den Weg, auf dem das Notfall-Passwort eingegeben wird: Passwort ohne Datei. Dort gibt es genau eine Antwort — „Schlüssel nicht erkannt“ —, gleich ob ein Notfall-Fach getroffen wurde oder gar nichts.

Wird dagegen eine Datei übergeben, sagt die App, was mit dieser Datei nicht stimmte: kein Schlüsseldateiformat, falsches Passwort, oder gültig aber ohne passendes Fach. Sonst wäre ein tippfehlerhaftes Passwort von einer verwechselten Datei nicht zu unterscheiden, und Nutzer stünden ohne jeden Anhaltspunkt da. Keine dieser drei Antworten verrät, ob es auf diesem Gerät überhaupt einen verborgenen Bereich gibt — sie beschreiben ausschließlich die eingereichte Datei. Und das Notfall-Passwort erreicht diesen Zweig nicht, weil es ohne Datei eingegeben wird.

Das Notfall-Passwort

Wird es im Feld des verborgenen Bereichs eingegeben, verschwindet dieser Bereich: Tresor B wird mit frischem Zufall überschrieben, und alle acht Fächer ebenso — damit ist auch die echte PEM-Datei ab da wertlos. Danach zeigt die App exakt dieselbe Meldung wie ein Fehlversuch ohne Datei: „Schlüssel nicht erkannt“.

Tresor A bleibt dabei unangetastet. Ein offener Bereich, der plötzlich leer ist, wäre genau das Signal, das die ganze Konstruktion vermeiden soll.

Was das nicht kann. Es holt die Vergangenheit nicht ein: ein Abbild dieses Geräts, das vorher gezogen wurde, lässt sich weiterhin mit der PEM-Datei öffnen. Und es erreicht das Relay nicht — der Notfall-Pfad hat die verborgene Identität nicht und kann sich dort nicht anmelden. Was dort liegt, ist unlesbares Chiffrat und verfällt binnen 24 Stunden. Zusätzlich gilt: in manchen Rechtsordnungen ist das Vernichten von Daten unter Zwang strafbar.

Was der Server sieht

Sieht erSieht er nicht
Öffentliche Schlüssel und die daraus abgeleitete Nutzer-ID
Zufällige Raum-IDs und wer sie abonniert
Zeitpunkt und Größe der Chiffrate
IP-Adressen der Verbindungen
Nachrichteninhalte
Raumnamen und Mitgliederlisten
Raumschlüssel oder irgendeinen privaten Schlüssel
SDP, ICE-Kandidaten, DTLS-Fingerabdrücke
Audio- oder Videodaten

Der Server ist ein Relay ohne Datenbank. Alles liegt im RAM, ist gedeckelt, verfällt nach 24 Stunden und wird gelöscht, sobald alle Mitglieder es abgeholt haben. Ein Prozess-Neustart löscht alles.

Nachrichten

Jeder Raum hat einen AES-256-GCM-Schlüssel. Der Klartext wird zuerst mit deinem Identitätsschlüssel signiert, dann verschlüsselt. Raum-ID und Schlüssel-ID hängen als additional authenticated data mit drin — ein Chiffrat lässt sich also nicht in einen anderen Raum umhängen.

Weil vor dem Verschlüsseln signiert wird, reicht der Raumschlüssel allein nicht, um sich als jemand anderes auszugeben: auch ein Gruppenmitglied kann keine Nachricht in fremdem Namen fälschen.

Räume und Schlüsselwechsel

Ein Raum mit zwei Mitgliedern ist ein Direktchat, mit mehr eine Gruppe — technisch dasselbe. Der Raumschlüssel wird einzeln für jedes Mitglied verpackt: ECDH mit einem Wegwerf-Schlüssel des Absenders gegen deinen öffentlichen ECDH-Schlüssel, HKDF-SHA-256, AES-256-GCM. Der Server transportiert das Paket, ohne es öffnen zu können.

Bei jeder Änderung der Mitgliederliste wird ein neuer Raumschlüssel erzeugt. Wer neu dazukommt, kann nichts Älteres lesen — auch nicht das, was noch in der Warteschlange des Servers liegt. Wer entfernt wird, kann nichts Neues mehr lesen, selbst wenn die Verbindung bestehen bleibt.

Anrufe

Sprach- und Videoanrufe laufen als P2P-Mesh: jedes Paar hat eine eigene Verbindung, WebRTC verschlüsselt sie mit DTLS-SRTP. Medien berühren den Server nie.

Der übliche Angriff auf WebRTC ist der Signalisierungsserver, der die DTLS-Fingerabdrücke im SDP austauscht und sich dazwischenschaltet. Hier geht das nicht: SDP und ICE-Kandidaten reisen durch denselben verschlüsselten Raumkanal wie Nachrichten. Das Relay sieht nur Chiffrat und kann nichts ersetzen. STUN und TURN laufen auf diesem Server, damit kein Dritter die IP-Adressen der Anrufenden erfährt; ein TURN-Relay leitet ohnehin nur bereits verschlüsselte Pakete weiter.

Mesh trägt etwa sechs Teilnehmende, dann limitiert der Upload.

Beschlagnahmtes Gerät

Was gefunden wird, hängt von der Stufe ab. Stufe 3 liegt nie auf dem Gerät — dort ist nichts zu finden, weil nie etwas geschrieben wurde. Stufe 2 liegt dort als Zufall: ohne die PEM-Datei ist nicht einmal erkennbar, dass es sie gibt. Stufe 1 ist ein erkennbarer, verschlüsselter Tresor — mit App-Passwort braucht es das Passwort, ohne genügt ein entsperrtes Gerät.

Das ist der bewusste Handel: Stufe 1 ist bequem und dafür nur so gut wie dein App-Passwort. Was das nicht aushalten soll, gehört in Stufe 2 oder 3.

Die Schlüsseldatei ist das ganze Konto. Leg sie nicht ins Downloads-Verzeichnis desselben Geräts — für die PEM-Datei des verborgenen Bereichs gilt das doppelt. Passwortmanager, USB-Stick oder verschlüsselter Datenträger, getrennt aufbewahrt. Mit Datei und Passphrase ist alles Zukünftige lesbar.

Wogegen das nicht hilft

Verwendete Verfahren

Identität / SignaturECDSA P-256, SHA-256
SchlüsselaustauschECDH P-256 → HKDF-SHA-256
Nachrichten & SignalisierungAES-256-GCM, 96-Bit-IV, AAD-gebunden
Schlüsseldatei / PEMPBKDF2-HMAC-SHA-256, 600 000 Runden → AES-256-GCM
Tresore auf dem GerätAES-256-GCM, auf feste Größenklassen gepolstert
App-PasswortPBKDF2-HMAC-SHA-256, 600 000 Runden → AES-256-GCM
Schlüsselfach aus der PEM-Dateistatisches ECDH P-256 → HKDF-SHA-256 → AES-256-GCM
MedienWebRTC DTLS-SRTP, P2P-Mesh
Bibliotheken im Browserkeine — ausschließlich Web Crypto

Der gesamte Client-Code liegt unter /js/ und ist unminifiziert lesbar. Prüfe ihn, statt dieser Seite zu glauben.