Zum Inhalt springen
ecdsa.com
C

libsodium

libsodium von Frank Denis, der portable Fork von NaCl: Ed25519-Signaturen mit strikter Prüfung, X25519, authentifizierte Verschlüsselung sowie ML-KEM-768 und das hybride KEM X-Wing – aber überhaupt kein ECDSA.
Lizenz
ISC
Geprüfte Version
1.0.22 ·
Quellcode
github.com/jedisct1/libsodium
Dokumentation
doc.libsodium.org/

Kompatibilität auf einen Blick

EdDSAPost-Quanten-Verfahren

EdDSA
Ed25519Ed25519ph
Formate privater Schlüssel
seed-32expanded-64

libsodium bietet eine kleine, bewusst kuratierte Auswahl an Primitiven hinter Funktionen, die sich nur schwer falsch verwenden lassen; die Bibliothek ist in PHP gebündelt, wird von vielen Bindings für andere Sprachen genutzt und steckt in Messaging-Apps. Signaturen gibt es nur mit Ed25519: Die Header von 1.0.22 (geprüft mit dem Paket aus Alpine 3.24.2) deklarieren keine ECDSA-Funktion; alles, was ES256 oder secp256k1 spricht, braucht also eine andere Bibliothek.

Das Signieren mit Ed25519 ist deterministisch, wie RFC 8032 es vorschreibt – zwei Signaturen derselben Nachricht waren identisch –, und die Funktionen crypto_sign_*_ph implementieren Ed25519ph, dessen Signaturen nicht mit einfachem Ed25519 austauschbar sind: Der einfache Verifizierer lehnte im Test eine solche Signatur ab. Der geheime Schlüssel ist 64 Byte lang, der 32-Byte-Seed gefolgt vom öffentlichen Schlüssel, während die meisten anderen Bibliotheken nur den Seed speichern; crypto_sign_ed25519_sk_to_seed und crypto_sign_seed_keypair konvertieren zwischen beiden Formen, wie das Beispiel zeigt.

Die Prüfung ist dort strikt, wo andere Implementierungen voneinander abweichen. Eine Signatur, in der S durch S + L ersetzt war – derselbe Wert modulo der Gruppenordnung, von RFC 8032 verboten –, wurde abgelehnt, ebenso eine Signatur, die gegen das neutrale Element, einen Punkt kleiner Ordnung, als öffentlichen Schlüssel geprüft wurde. Bibliotheken, die solche Eingaben akzeptieren, kommen in Grenzfällen zu einem anderen Ergebnis als libsodium – wichtig für Konsenssysteme, die sich über die Gültigkeit einig sein müssen. crypto_sign_verify_detached nimmt keine Signaturlänge entgegen und liest genau 64 Byte; prüfe die Länge also, bevor du die Funktion aufrufst.

Die Post-Quanten-Unterstützung in 1.0.22 beschränkt sich auf Schlüsselkapselung: crypto_kem_mlkem768_* (öffentliche Schlüssel mit 1.184 Byte, Chiffrate mit 1.088 Byte) und das hybride X-Wing (crypto_kem_xwing_*, 1.216 und 1.120 Byte), das auch die generischen Funktionen crypto_kem_* standardmäßig verwenden. ML-DSA oder andere Post-Quanten-Signaturen gibt es nicht. Schlüssel sind durchweg rohe Bytes – öffentliche Schlüssel und Seeds mit 32 Byte –, ohne Unterstützung für PEM, DER oder JWK. Vergleiche die Größen der KEMs im Post-Quanten-KEM-Playground.

Fakten und die Prüfungen dahinter

Nichts im Folgenden ist aus einer Dokumentation abgeschrieben. Das Prüfskript content/libraries/verify/libsodium/run.sh hat libsodium 1.0.22 am 20. Oktober 2026 im Container-Image alpine:3.24.2 ausgeführt; die Seite muss mit seiner Ausgabe übereinstimmen, und jeder Fakt führt die zugehörigen Zeilen auf.

  • ECDSA-Kurven

    none

    Kein ECDSA: crypto_sign_PRIMITIVE ist ed25519, und kein Header deklariert eine ECDSA-Funktion.

    Von der Prüfung aufgezeichnet
    fact ecdsa-curves = none
    evidence ecdsa-curves: crypto_sign_PRIMITIVE is "ed25519"; the header set declares no ECDSA functions
  • EdDSA

    Ed25519Ed25519ph

    Ed25519 über crypto_sign_* und Ed25519ph über crypto_sign_init, _update und _final_*; der einfache Verifizierer lehnt Ed25519ph-Signaturen ab.

    Von der Prüfung aufgezeichnet
    fact eddsa = Ed25519, Ed25519ph
    evidence eddsa: crypto_sign_final_verify (Ed25519ph) accepts its signature: yes; the plain verifier rejects it: yes
  • Deterministische Ed25519-Signaturen

    yes

    Zwei Signaturen derselben Nachricht mit demselben Schlüssel waren identisch.

    Von der Prüfung aufgezeichnet
    fact ed25519-deterministic = yes
  • Aufbau des privaten Schlüssels (Ed25519)

    expanded-64

    crypto_sign_SECRETKEYBYTES ist 64: der Seed, gefolgt vom öffentlichen Schlüssel.

    Von der Prüfung aufgezeichnet
    fact ed25519-private-key = expanded-64
    evidence ed25519-private-key: crypto_sign_SECRETKEYBYTES = 64: the 32-byte seed followed by the 32-byte public key (seed matches: yes)
  • Ed25519-Signatur mit nicht kanonischem S

    rejected

    Eine Signatur, in der S durch S + L ersetzt war, wurde abgelehnt.

    Von der Prüfung aufgezeichnet
    fact ed25519-non-canonical-s = rejected
  • Öffentlicher Schlüssel kleiner Ordnung (Ed25519)

    rejected

    Bei der Prüfung gegen das neutrale Element als öffentlichen Schlüssel wurde die Signatur abgelehnt.

    Von der Prüfung aufgezeichnet
    fact ed25519-small-order-key = rejected
    evidence ed25519-small-order-key: the identity point as public key with R = identity, S = 0
  • Fehlerhafte Ed25519-Signatur

    rejected

    Bei 64 Byte Datenmüll gab crypto_sign_verify_detached -1 zurück.

    Von der Prüfung aufgezeichnet
    fact ed25519-malformed-signature = rejected
    evidence ed25519-malformed-signature: 64 bytes of 0xab: crypto_sign_verify_detached returned -1; the function takes no length and reads exactly crypto_sign_BYTES = 64 bytes
  • Signaturmodi

    detachedcombined

    Abgetrennte Signaturen (Detached Signatures, 64 Byte) und kombinierte signierte Nachrichten (Signatur vor der Nachricht) stehen beide zur Verfügung.

    Von der Prüfung aufgezeichnet
    fact signature-modes = detached, combined
    evidence signature-modes: crypto_sign prepends the 64-byte signature to the message: 82 bytes for a 18-byte message
  • Post-Quanten-Algorithmen

    ML-KEMX-Wing

    Kapselung und Entkapselung funktionierten mit ML-KEM-768 (crypto_kem_mlkem768_*) und X-Wing (crypto_kem_xwing_*, Standard der generischen Funktionen crypto_kem_*); Post-Quanten-Signaturen gibt es nicht.

    Von der Prüfung aufgezeichnet
    fact pqc = ML-KEM, X-Wing
    evidence pqc: crypto_kem_mlkem768: public key 1184 bytes, ciphertext 1088 bytes
    evidence pqc: crypto_kem_xwing: public key 1216 bytes, ciphertext 1120 bytes; generic crypto_kem_primitive() is "xwing"
  • Formate öffentlicher Schlüssel

    raw-32

    Öffentliche Schlüssel sind 32 rohe Bytes; PEM, DER oder JWK werden nicht unterstützt.

    Von der Prüfung aufgezeichnet
    fact public-key-formats = raw-32
  • Formate privater Schlüssel

    seed-32expanded-64

    Schlüssel werden aus einem 32-Byte-Seed abgeleitet (crypto_sign_seed_keypair) und als 64 Byte gespeichert; crypto_sign_ed25519_sk_to_seed gewinnt den Seed zurück.

    Von der Prüfung aufgezeichnet
    fact private-key-formats = seed-32, expanded-64
    evidence private-key-formats: crypto_sign_seed_keypair reproduces the key from the seed: yes; crypto_sign_ed25519_sk_to_seed recovers it: yes

Verwendung

Erzeuge einen Ed25519-Schlüssel, extrahiere den 32-Byte-Seed, den andere Bibliotheken erwarten, und signiere und prüfe eine abgetrennte Signatur.
#include <sodium.h>
#include <stdio.h>
#include <string.h>

int main(void) {
    if (sodium_init() < 0) return 1;
    const unsigned char msg[] = "order #1042 approved";
    unsigned char pk[crypto_sign_PUBLICKEYBYTES], sk[crypto_sign_SECRETKEYBYTES];
    unsigned char sig[crypto_sign_BYTES], seed[32];

    crypto_sign_keypair(pk, sk);
    /* Other libraries store the 32-byte seed; libsodium's secret key is seed || public key. */
    crypto_sign_ed25519_sk_to_seed(seed, sk);

    /* Detached signature: 64 bytes, deterministic per RFC 8032. */
    crypto_sign_detached(sig, NULL, msg, sizeof msg - 1, sk);
    int ok = crypto_sign_verify_detached(sig, msg, sizeof msg - 1, pk) == 0;

    printf("secret key %d bytes, seed %zu bytes, signature %d bytes, verified: %d\n",
           crypto_sign_SECRETKEYBYTES, sizeof seed, crypto_sign_BYTES, ok);
    return 0;
}

Die Snippet-Testumgebung führt jedes Beispiel unverändert im Container-Image alpine:3.24.2 aus, und der Lauf schlägt fehl, wenn die Ausgabe nicht übereinstimmt.

Einrichtung
apk add --no-cache -q build-base libsodium-dev=1.0.22-r0 >/dev/null
Befehl
cc -o usage usage.c -lsodium && ./usage
Ausgabe muss passen (regulärer Ausdruck)
secret key 64 bytes, seed 32 bytes, signature 64 bytes, verified: 1

Bibliotheken