Saltar al contenido principal
de/blog/kyber/la-capa-que-falla/

Die Schicht, die versagt — Die Distanz des Geheimnisses — II

Von Xscriptor — Óscar Preciado7 Min. Lesezeit
PhilosophieTechnologieKryptographieEssayKryptographiePost-QuantenKyberFlutterDartSeitenkanalTiming-AngriffImplementierungXscriptorÓscar Preciado
Die Schicht, die versagt — Die Distanz des Geheimnisses — II

Ein perfekter Algorithmus, der falsch implementiert ist, ist einfach unsicher.



Kyber ist sicher. Die Mathematik ist veröffentlicht, peer-reviewed, jahrelang analysiert. Die Parameter sind mit konservativen Margen gewählt. Die Module-LWE-Struktur ist elegant und solide.

Aber Kyber lebt nicht auf Papier. Es lebt in Code. Und Code hat ein Problem, das Gleichungen nicht kennen: Die Zeit ist nicht einheitlich.

Die Zeit als Orakel

Timing-Angriffe nutzen eine grundlegende Diskrepanz zwischen dem mathematischen Modell und der realen Maschine aus. Im Modell dauert eine Operation wie x + y "eine Zeiteinheit". In der realen Maschine kann x + y je nach den Werten von x und y, je nach Cache-Zustand, je nach Sprungvorhersage des Prozessors verschiedene Mikrosekunden dauern.

Für die Kryptographie ist dies eine Katastrophe: Wenn die Entschlüsselungszeit vom Geheimnis abhängt, kann der Angreifer die Zeit messen und das Geheimnis wiederherstellen.

// Illustratives Beispiel: Ein NICHT zeitkonstanter Vergleich
bool vergleichen(List<int> a, List<int> b) {
  if (a.length != b.length) return false;
  for (int i = 0; i < a.length; i++) {
    if (a[i] != b[i]) return false; // early exit: Zeit hängt davon ab, wo es fehlschlägt
  }
  return true;
}

Diese Funktion gibt false zurück, sobald sie eine Abweichung findet. Wenn das erste Byte fehlschlägt, dauert es kurz. Wenn das letzte fehlschlägt, dauert es länger. Ein Angreifer, der die Zeit dieses Vergleichs messen kann, kann ableiten, wie viele Bytes korrekt waren, und damit die Sicherheit Byte für Byte brechen.

Flutter und das gebrochene Versprechen

Dart ist eine Sprache, die keine konstante Zeit auf VM-Ebene garantiert. Es gibt kein @ConstantTime und kein Compiler-Attribut, das sicherstellt, dass eine Operation unabhängig von ihren Operanden gleich lange dauert.

Problem: Dart VM → keine Garantien für konstante Zeit
Kontext: Flutter für plattformübergreifende mobile Anwendungen

Konkrete Risiken bei der Implementierung von Kyber in reinem Dart:

  1. Vergleich von Ciphertexts  →  Timing des FO-Transforms (der kritischste Schritt)
  2. Decodierung von Polynomen  →  Timing von Compress/Decompress
  3. NTT (Number Theoretic Transform) →  Tabellenzugriff nach geheimem Index
  4. CBD-Sampling  →  Verzweigung nach Geheimnisbits
  5. Deserialisierung von Schlüsseln  →  implizite Länge oder variierendes Padding

Jeder dieser Punkte ist ein Angriffsvektor. Nicht weil Kyber schwach wäre — die Gleichungen sind korrekt — sondern weil die Implementierung in Dart Informationen durch die Zeit preisgibt.

Das Problem ist nicht auf Dart beschränkt. Jede Sprache ohne feine Kontrolle über die Ausführungszeit — JavaScript, Python, Java ohne extreme Sorgfalt — leidet unter demselben Problem. Der Unterschied ist, dass Flutter/Dart zunehmend für Anwendungen verwendet wird, die Kryptographie benötigen (Signal, Finanzanwendungen, verschlüsselte Nachrichten), und die Versuchung, "Kyber in reinem Dart zu schreiben, es ist ja Post-Quanten", ist groß.

Borges stellte sich ein Imperium vor, in dem die Kartografen eine so genaue Karte schufen, dass sie Punkt für Punkt mit dem Territorium übereinstimmte, bis sie unbrauchbar wurde. In der Kryptographie geschieht das Gegenteil: Das Paper ist die perfekte Karte — jede Operation definiert, jeder Parameter gerechtfertigt, jeder Schritt verifiziert — und die Implementierung ist das Territorium, das nie vollständig mit der Karte übereinstimmt. Zwischen Papier und Maschine klafft ein Raum, den kein Theorem schließen kann.

Ich habe es selbst erfahren. Während meiner Lernphase habe ich Kyber in Dart/Flutter implementiert — xkyber_crypto — exakt nach FIPS 203: NTT, CBD, FO-Transform, Compress/Decompress. Die Black-Box-Tests bestanden. Die Testvektoren der Spezifikation stimmten Byte für Byte überein. Die Implementierung war mathematisch korrekt. Und dennoch war sie kryptographisch nicht vertretbar.

Das Paper geht von einem idealen Modell aus, in dem jede Instruktion gleich viel kostet. Das Territorium — die Dart-VM, der JIT-Compiler, die Cache-Hierarchie des Prozessors — macht diese Annahme nicht. Das Paper erwähnt nicht, dass der Zugriff auf eine NTT-Tabelle über einen vom Geheimnis abgeleiteten Index das Geheimnis preisgeben kann. Das Paper weiß nicht, was ein Cache ist.

Sartre sagte, die Hölle, das sind die anderen. Für das Kyber-Paper sind die anderen die physische Welt, in der es ausgeführt werden muss: der RAM, der Garbage Collector, der Sprungvorhersager, die VM, die Anweisungen umordnet, ohne zu fragen. Das Repository ist seit November 2025 archiviert als Zeugnis dafür, dass die Distanz zwischen Karte und Territorium nicht immer überbrückt werden kann.

Der Unterschied zwischen Karte und Territorium

Die Forschung zur Implementierung von Kyber dokumentiert präzise die Optimierungen, die für zeitkonstanten Code notwendig sind: die Verwendung der Montgomery-Reduktion anstelle von Division, das Fehlen von if in Sampling-Funktionen, der sequenzielle Zugriff auf NTT-Tabellen ohne Abhängigkeit von geheimen Daten.

Schicht  Was sie verspricht           Was fehlschlagen kann
─────    ───────────────────           ────────────────
Mathematik LWE-Sicherheit             Kein Fehler (korrekt)
Algorithmus FO-Transform CCA-sicher   Kein Fehler (korrekt)
Sprache   Ausdrucksstärke             Keine Garantien für konstante Zeit
CPU       Ausführung                  Cache, Prädiktoren, Pipeline

Jede Schicht führt neue Risiken ein. Ein mathematisch perfekter Algorithmus, implementiert in einer Sprache, die keine konstante Zeit garantiert, ausgeführt auf einer CPU, die dynamisch optimiert: Die von den Gleichungen versprochene Sicherheit sickert durch jeden Spalt der Hardware.

Sartre schrieb, dass "die Hölle, das sind die anderen". In der Kryptographie ist die Hölle die anderen Schichten: der Compiler, der Operationen umordnet, der Cache, der Zugriffe preisgibt, der Garbage Collector, der messbare Pausen einführt.

// Zeitkonstante Implementierung (C) — jeder Zweig dauert gleich lang
uint8_t ct_compare(const uint8_t *a, const uint8_t *b, size_t len) {
    uint8_t result = 0;
    for (size_t i = 0; i < len; i++) {
        result |= a[i] ^ b[i];  // XOR: kein early exit
    }
    return result;  // 0 wenn gleich, != 0 wenn unterschiedlich
}

In C ist diese Funktion zeitkonstant (vorausgesetzt, der Compiler optimiert sie nicht). In Dart gibt es keine Möglichkeit zu garantieren, dass die VM diese Schleife als eine Schleife ohne datenabhängige Verzweigung kompiliert. Dieselbe Logik führt je nach Sprache zu unterschiedlichen Sicherheitsergebnissen.

Was nicht im Paper steht

Das Kyber-Paper (Bos et al., 2018) beschreibt den Algorithmus. Es beschreibt nicht, wie man ihn auf jeder Plattform sicher implementiert. Es warnt nicht davor, dass ein naiver Vergleich von Ciphertexts in Dart den Schlüssel preisgeben kann. Es erwähnt nicht, dass die Dart-VM Zeitvariationen einführen kann, die die Sicherheit des FO-Transforms zunichtemachen.

Diese Distanz — zwischen dem Paper und dem Produkt — ist der Ort, an dem die meisten realen kryptographischen Schwachstellen auftreten. Nicht in den Gleichungen. In den Implementierungsentscheidungen.

Schicht Wo ist das Risiko dokumentiert?
Algorithmus Paper, FIPS 203
Parameter Paper, FIPS 203
Sichere Implementierung in C Referenz von pq-crystals
Sichere Implementierung in Rust Bindings, Wrapper
Sichere Implementierung in Dart Es gibt keine offizielle Dokumentation
Implementierung in Flutter Gibt es nicht

Es ist nicht so, dass Kyber nicht sicher in Dart implementiert werden könnte. Es ist so, dass dies ein Maß an Sorgfalt — und Wissen über die Dart-VM — erfordert, das nirgendwo dokumentiert ist. Jede Implementierung in reinem Dart ist heute, hier und jetzt, eine Wette.


In III: Die Grenze des Fehlers werden wir die physikalische Grenze der Kryptographie erkunden: die Energie, die nötig ist, um ein Schema zu brechen, die Landauer-Grenze und warum selbst Kyber — wie alles andere — dazu bestimmt ist zu fallen, wenn auch vielleicht nicht aus den Gründen, die wir erwarten.


Querverweise zur Forschung: