‹ Alle Artikel

Ende-zu-Ende-Verschlüsselung in einer Mobile-App

Drei Plattformen, drei Krypto-Wege — und alles lief. Warum wir trotzdem auf AES-256-GCM vereinheitlicht haben, und was mit den alten Nachrichten passiert.

„Ende-zu-Ende-verschlüsselt" steht auf vielen Apps. Es ist ein Versprechen mit einer harten Konsequenz: Wenn es stimmt, kann der Betreiber die Nachrichten nicht lesen. Auch nicht, wenn er möchte.

Wir haben das für die Chats in Anirova gebaut — plattformübergreifend, aus gemeinsamem Kotlin-Code für iOS und Android. Der interessanteste Teil war nicht der Aufbau. Es war die Konsolidierung danach.

Wie drei Plattformen auseinanderdriften

Kryptografie ist Betriebssystem-Sache. Android bringt andere Bibliotheken mit als iOS, das Web wieder andere. Kotlin Multiplatform teilt den Code — aber an dieser Grenze muss jede Plattform ihren eigenen Weg gehen.

Das Ergebnis nach einiger Zeit sah so aus:

  • Android und Web: AES-256-GCM
  • iOS: AES-CBC mit HMAC — mit anderer Nonce-Länge (16 statt 12 Byte) und anderer Tag-Länge (32 statt 16)

Niemand hatte das so entschieden. Es war gewachsen: Jede Plattform nahm, was ihre Bibliothek am bequemsten anbot. Alles funktionierte. Trotzdem war es ein Problem.

Drei Plattformen, drei Krypto-Wege — das heißt drei Stellen, an denen ein Fehler stecken kann, und drei Stellen, die bei jeder Änderung gleichzeitig richtig bleiben müssen.

Warum das gefährlich ist, obwohl es läuft

Ein normaler Fehler zeigt sich: Etwas stürzt ab oder sieht falsch aus. Ein Krypto-Fehler zeigt sich nicht. Die Nachricht kommt an, sieht richtig aus — und ist trotzdem angreifbar.

AES-CBC mit HMAC ist nicht per se unsicher. Aber es ist ein zusammengesetztesVerfahren: Man verschlüsselt, und man authentifiziert — in der richtigen Reihenfolge, mit getrennten Schlüsseln. Wer die Reihenfolge vertauscht, baut eine Lücke, die kein Test findet, weil ja alles ankommt.

AES-GCM erledigt beides in einem Schritt. Es ist ein authentifiziertes Verfahren: Manipulation wird erkannt, nicht falsch entschlüsselt. Die Klasse von Fehlern, die beim Zusammensetzen entsteht, gibt es dort nicht.

Die Konsolidierung

Also haben wir vereinheitlicht — ein Verfahren für alle Plattformen:

  • AES-256-GCM, 12-Byte-Nonce, 16-Byte-Tag
  • HKDF-SHA256 für die Schlüsselableitung
  • iOS über CryptoKit auf denselben Stand gebracht

Klingt nach einem Nachmittag Arbeit. Ist es nicht — wegen der Nachrichten, die schon verschlüsselt in der Datenbank liegen.

Das eigentliche Problem: Altbestand

Verschlüsselte Daten kann man nicht einfach migrieren. Der Server kann sie nicht lesen, also auch nicht umschlüsseln — das ist ja der Sinn der Sache. Die Nachrichten von gestern müssen morgen noch lesbar sein, mit dem alten Verfahren.

Der Weg dahin ist unspektakulär und funktioniert:

  • Jede Nachricht trägt ein Label, das ihr Verfahren nennt.
  • Neue Nachrichten bekommen ausschließlich das neue Label.
  • Das alte Label bleibt lesend gültig — für immer, oder bis die letzte Altnachricht weg ist.

Der entscheidende Punkt: Der alte Pfad darf nur noch entschlüsseln, nie verschlüsseln. Sonst wächst der Altbestand weiter, und die Umstellung ist nie fertig. Das steht bei uns als Kommentar direkt über der Konstante — damit es niemand aus Versehen wieder benutzt.

Was Krypto-Code an Tests braucht

Bei Verschlüsselung ist „es funktioniert" die schwächste aller Aussagen. Interessant ist, ob die Fälle scheitern, die scheitern müssen. Unsere Sicherheitstests prüfen deshalb vor allem das:

  • Wird ein umgekipptes Bit in der Chiffre erkannt — oder still falsch entschlüsselt?
  • Wird ein manipulierter Auth-Tag erkannt?
  • Was passiert mit dem falschen Schlüssel? (Erwartung: erkannt, nicht Müll ausgeben.)
  • Wird ein fehlender Schlüssel von einer kaputten Nachricht unterschieden?
  • Ungültige Eingaben — sauberer Fehler oder undefiniertes Verhalten?

Kein einziger dieser Tests fragt „kommt die Nachricht an". Das ist der Punkt.

Was uns die Sache gelehrt hat

Ende-zu-Ende-Verschlüsselung ist kein Feature, das man später einbaut. Sie bestimmt das Datenmodell: Was verschlüsselt ist, kann der Server nicht durchsuchen, nicht sortieren, nicht filtern. Wer Volltextsuche über Chats verspricht und gleichzeitig Ende-zu-Ende-Verschlüsselung, hat eines von beidem nicht verstanden.

Und die unbequemere Lehre: Plattformübergreifend heißt nicht automatisch einheitlich. Der geteilte Code verführt zu der Annahme, alles laufe gleich. An den Stellen, wo jede Plattform ihre eigene Bibliothek nutzt, driftet es auseinander — langsam, unauffällig, und niemand merkt es, weil alles funktioniert. Genau dort lohnt es sich, regelmäßig nachzusehen.

Projekt im Kopf?

Wenn Sie an ähnlichen Problemen sitzen — wir bauen Software, die solche Fallen umgeht.

✉ andreklein99@gmx.de