2 Punkte von GN⁺ 2026-01-01 | 1 Kommentare | Auf WhatsApp teilen
  • In der Low-Level-Funktion crypto_core_ed25519_is_valid_point() von libsodium wurde ein Fehler bei der unzureichenden Punktvalidierung auf der Edwards25519-Kurve entdeckt
  • Die Funktion sollte prüfen, ob ein Punkt zur primären kryptografischen Gruppe gehört, ließ aber fälschlich einige Punkte aus gemischten Ordnungen (subgroup) passieren
  • Ursache war ein Codefehler bei der internen Koordinatenprüfung: Es wurde nur X=0 geprüft, die Prüfung Y=Z jedoch ausgelassen, sodass ungültige Punkte als gültig behandelt werden konnten
  • In der korrigierten Version werden nun beide Bedingungen (X=0, Y=Z) geprüft; betroffen sind Versionen bis einschließlich 1.0.20 bzw. Releases vor dem 30. Dezember 2025
  • Die High-Level-API (crypto_sign_*) ist nicht betroffen; die Verwendung der Ristretto255-Gruppe wird im Hinblick auf Sicherheit und Performance empfohlen

Überblick über das libsodium-Projekt

  • libsodium ist ein vor 13 Jahren gestartetes Projekt, das darauf abzielt, Kryptografie mit einer einfachen API leicht nutzbar zu machen
    • Es wurde so entworfen, dass Nutzer nur High-Level-Operationen ausführen müssen, ohne die internen Algorithmen kennen zu müssen
  • Das Projekt legt großen Wert auf Kompatibilität der API und hat auf Basis der NaCl-API bis heute Konsistenz bewahrt
  • Da einige Nutzer Low-Level-Funktionen direkt verwenden und dabei über die in der Dokumentation genannten Grenzen hinausgehen, wird die Bibliothek zunehmend wie ein Kryptografie-Toolkit eingesetzt

Ursache des entdeckten Bugs

  • Betroffene Funktion: crypto_core_ed25519_is_valid_point()
    • Sie sollte Punkte ablehnen, die auf der Edwards25519-Kurve nicht zur primären Gruppe (Ordnung L) gehören
    • Einige Punkte mit gemischter Ordnung (2L, 4L, 8L usw.) bestanden die Prüfung jedoch
  • Intern wird zur Bestimmung der Punktordnung mit L multipliziert und anschließend geprüft, ob das Ergebnis der neutrale Punkt (identity) ist
    • Der neutrale Punkt wird in der Form X=0, Y=Z dargestellt, aber der bisherige Code prüfte nur X=0
    • Dadurch konnten fehlerhafte Punkte mit Y≠Z als gültig behandelt werden
  • Beispiel: Addiert man zu einem Punkt Q der primären Gruppe den Punkt der Ordnung 2 (0, -1), dann ist Q+(0, -1) ein ungültiger Punkt, wurde vor dem Fix aber akzeptiert

Inhalt der Korrektur

  • Der Patch-Commit enthält folgende Änderung
    • Bisheriger Code: return fe25519_iszero(pl.X);
    • Korrigierter Code: fe25519_sub(t, pl.Y, pl.Z); return fe25519_iszero(pl.X) & fe25519_iszero(t);
  • Jetzt werden sowohl X=0 als auch Y=Z geprüft, wodurch die Validierung korrekt erfolgt

Auswirkungsbereich

  • Betroffen sein können Fälle mit folgenden Bedingungen
    • Verwendung von Version 1.0.20 oder älter bzw. Releases vor dem 30. Dezember 2025
    • Validierung nicht vertrauenswürdiger Eingabepunkte mit crypto_core_ed25519_is_valid_point()
    • Nutzer, die Edwards25519-Kurvenoperationen direkt implementieren
  • Die meisten Nutzer sind jedoch nicht betroffen
    • Die High-Level-API (crypto_sign_*) verwendet diese Funktion nicht
    • crypto_scalarmult_ed25519 führt auch mit fehlerhaften öffentlichen Schlüsseln nicht zu Informationslecks
    • Mit crypto_sign_keypair und crypto_sign_seed_keypair erzeugte Schlüssel gehören zur korrekten Gruppe

Empfohlene Maßnahmen

  • Die Verwendung der Ristretto255-Gruppe wird empfohlen
    • Sie ist seit 2019 in libsodium enthalten und löst Probleme im Zusammenhang mit dem Cofactor
    • Dekodierte Punkte sind automatisch sicher, eine zusätzliche Validierung ist nicht erforderlich
    • Sie bietet schnellere Rechenleistung als Edwards25519
  • Falls ein Update nicht möglich ist, kann zur Validierung die vorgeschlagene Alternative auf Anwendungsebene (is_on_main_subgroup) verwendet werden

Korrigierte Distributionen und Support

  • Das Problem wurde unmittelbar nach der Entdeckung behoben und ist in allen stabilen Versionen enthalten, die nach dem 30. Dezember 2025 veröffentlicht wurden
    • Einschließlich offiziellem Tarball, Visual Studio/MingW-Binärdateien, NuGet-Paketen, Builds für Android, swift-sodium xcframework, Rust libsodium-sys-stable und libsodium.js
  • Ein neuer Point Release ist ebenfalls geplant
  • Das Projekt wird von einem einzelnen Maintainer betreut; laufende Verbesserungen können über OpenCollective-Sponsoring unterstützt werden

1 Kommentare

 
GN⁺ 2026-01-01
Hacker-News-Kommentare
  • Auch die PHP-Bibliothek sodium_compat war von diesem Problem betroffen.
    Details dazu finden sich in security-advisories PR #756.
    Heute Abend will ich alle anderen Ed25519-Implementierungen im Open-Source-Ökosystem prüfen, um festzustellen, ob dort derselbe Prüfungsfehler fehlt.

    • Ich habe festgestellt, dass in einigen Bibliotheken die Validierungslogik komplett fehlt.
      Aber es gab keine falsch implementierten Fälle wie bei der oben erwähnten Schwachstelle.
      Wenn ich keine E-Mail geschickt habe, steht es wahrscheinlich nicht auf ianix’ Ed25519-Deployment-Liste, ich habe es übersehen oder es ist eine sichere Implementierung.
    • Ich möchte meinen Dank dafür aussprechen, dass du zu Open Source beigetragen hast.
  • Seit vier Monaten entwickle ich sodium-Bindings für Lean4.
    Ich bin jetzt beim Schritt Ristretto255 angekommen und verstehe inzwischen, warum der Autor von dieser Technik so begeistert ist.
    Ristretto ist eine ausgeklügelte API, mit der sich auf Curve25519 beliebige Polynome konstruieren lassen, und das Experimentieren damit macht wirklich Spaß.
    Falls der Autor diesen Beitrag sieht, möchte ich mich aufrichtig bedanken.

    • Ich würde gern wissen, ob es für dieses Projekt ein öffentliches Repository gibt.
  • Das Ziel von Libsodium war, keine Low-Level-Funktionen, sondern eine High-Level-API bereitzustellen.
    Es wurde so entworfen, dass Nutzer die internen Algorithmen nicht kennen müssen, aber mit der Zeit nahmen die Fälle zu, in denen Low-Level-Funktionen direkt verwendet wurden.
    Am Ende wurde Libsodium wie ein Algorithmus-Toolkit verwendet.
    Entscheidend ist, zu erkennen, in welche Richtung die Nutzer wollen, und dem Projekt nicht nur eine bestimmte Nutzungsweise aufzuzwingen.
    Manche Projekte werden in diesem Punkt dogmatisch und scheitern daran.

    • Interessanter Punkt. Umgekehrt kann aber auch das, was Nutzer zu wollen glauben, von dem abweichen, was sie tatsächlich brauchen.
      Es ist riskant, wenn Nichtfachleute kryptographische Primitive direkt verwenden.
      Libsodium wurde so entworfen, dass Nutzer sich nicht selbst in Gefahr bringen.
      Idealerweise sollte eine Bibliothek Fehlbenutzung unmöglich machen.
      Dazu empfehle ich den Artikel „If You're Typing The Letters A-E-S Into Your Code, You're Doing It Wrong”.
    • Wenn man alle internen Funktionen als API-Vertrag betrachtet, führt fast jede Änderung zu einem Kompatibilitätsbruch.
      Deshalb ist es oft die richtige Entscheidung, einige Funktionen auf private oder internal zu beschränken.
      Ich bin mir nicht sicher, ob Libsodium diese Grenze gut gezogen hat, aber das Gleichgewicht ist wichtig.
    • Früher habe ich ein C++-Test-Framework namens CeeFIT entwickelt und war stolz darauf, Fixtures zur Compile-Zeit zu registrieren.
      Einige Nutzer verwendeten es dann jedoch wie einen Batch-Runner.
      Um ihre Anforderungen zu unterstützen, habe ich ein paar Bugs behoben.
      Letztlich habe ich mich einfach darüber gefreut, dass es überhaupt Nutzer gab.
  • Dieser Bug ist ein subtiler, aber wichtiger Fehler bei kryptographischer Validierung.
    Die einfache Prüfung „ist es gültig?“ ist in Wirklichkeit sehr komplex.
    Wenn Punkte außerhalb der Untergruppe mit Primordnung zugelassen werden, mag das nicht sofort wie eine Schwachstelle wirken, kann aber Annahmen in höheren Schichten zerstören.
    Außerdem werden Low-Level-Primitive viel breiter wiederverwendet als beabsichtigt, sodass ein kleiner Validierungsfehler große Auswirkungen haben kann.

    • Allerdings wurden X25519 und Ed25519 von vornherein so entworfen, dass eine solche Prüfung nicht nötig ist.
      Probleme mit Untergruppen entstehen erst, wenn man auf Curve25519 komplexere Protokolle baut.
      Deshalb bilde ich möglichst alle Punkte wieder auf die Untergruppe mit Primordnung ab.
      Monocypher hat solche fortgeschrittenen Funktionen.
      Dazu gehören zum Beispiel crypto_x25519_dirty_fast() oder crypto_elligator_map().
      Diese „dirty“-Funktionen erzeugen öffentliche Schlüssel, die die gesamte Kurve abdecken und von Zufälligkeit nicht zu unterscheiden sind.
      Danach lässt sich beim X25519-Schlüsselaustausch trotzdem dasselbe gemeinsame Geheimnis erhalten.
      Das ist DJBs Design zu verdanken, denn selbst bei anomalen öffentlichen Schlüsseln wird das gemeinsame Geheimnis auf die Untergruppe mit Primordnung abgebildet.
      Letztlich braucht man Ristretto nur dann, wenn eine solche Rückabbildung nicht möglich ist.
      Natürlich ist die Abstraktion einer Gruppe mit Primordnung nützlich, aber wer solche Protokolle entwerfen kann, sollte auch mit einem nichttrivialen Cofaktor umgehen können.
  • Wer in einem Großunternehmen arbeitet, sollte erwägen, Frank auf Unternehmensebene zu unterstützen.

    • Ich arbeite bei Apple, aber ich weiß nicht, wer Frank ist, und kenne auch den Sponsoring-Prozess nicht.
      Selbst wenn ich es wüsste, müsste ich ihn wohl eher aus eigener Tasche unterstützen als über ein Firmenkonto.
  • Ich frage mich, ob libnacl ebenfalls betroffen ist.
    Ich verwende täglich Software, die mit libnacl kompiliert wurde, aber nichts, das mit „libsodium“ kompiliert wurde.

  • Wirklich eine hervorragende Bibliothek.
    Vielen Dank an Frank Denis.