Zum Inhalt springen
ecdsa.com
C

liboqs (Open Quantum Safe)

liboqs, die C-Bibliothek des Projekts Open Quantum Safe für Post-Quanten-KEMs und -Signaturen: ML-KEM, ML-DSA und SLH-DSA neben einer langen Liste von Kandidaten hinter einer API – nach den Worten der Autoren gedacht für Forschung und Prototyping.
Lizenz
MIT
Geprüfte Version
0.16.0 ·
Quellcode
github.com/open-quantum-safe/liboqs
Dokumentation
openquantumsafe.org/liboqs/

Kompatibilität auf einen Blick

Post-Quanten-Verfahren

EdDSA
none
Post-Quanten-Algorithmen
ML-KEMML-DSASLH-DSAFalconHQCClassic-McElieceFrodoKEMBIKENTRUsntrup761KyberMAYOCROSSUOVSNOVAMQOM

liboqs bündelt Implementierungen von Schlüsselkapselungsverfahren (OQS_KEM) und Signaturverfahren (OQS_SIG) der Post-Quanten-Kryptografie hinter einer C-API und bildet den Kern des Open-Quantum-Safe-Providers für OpenSSL 3. Die Fakten auf dieser Seite wurden mit Release 0.16.0 (Commit 5a1a854b0dc9) geprüft, gebaut mit den Standardoptionen von CMake, die für die symmetrischen Primitive OpenSSL verwenden. Im README steht in Großbuchstaben: „WIR EMPFEHLEN DERZEIT NICHT, SICH IN EINER PRODUKTIONSUMGEBUNG AUF DIESE BIBLIOTHEK ZU VERLASSEN ODER SIE ZUM SCHUTZ SENSIBLER DATEN EINZUSETZEN.“ Was die Haupt-APIs für ML-KEM und ML-DSA im Produktionseinsatz mitbringen, führen die Seiten zu OpenSSL, BoringSSL, AWS-LC und Bouncy Castle auf.

Der Standard-Build aktivierte 41 KEMs und 221 Parametersätze für Signaturen, und je ein Parametersatz jeder Familie durchlief einen vollständigen Roundtrip: die NIST-Standards ML-KEM, ML-DSA und SLH-DSA (156 SLH-DSA-Varianten, rein und mit Pre-Hash), Falcon, die KEM-Kandidaten HQC, Classic McEliece, FrodoKEM, BIKE, NTRU und sntrup761, das vorstandardisierte Kyber sowie die zusätzlichen Signaturkandidaten MAYO, CROSS, UOV, SNOVA und MQOM. Schreibe in neuem Code ML-KEM-768, nicht Kyber768. Im Standard-Build ist kein Parametersatz für XMSS oder LMS aktiviert.

ML-DSA signiert im Hedged-Modus: Zwei Signaturen derselben Nachricht mit demselben Schlüssel unterschieden sich, Tests müssen Signaturen also prüfen, statt Bytes zu vergleichen. Kontext-Strings nach FIPS 204 werden über OQS_SIG_sign_with_ctx_str unterstützt; eine unter dem Kontext invoice-v1 erstellte Signatur scheiterte unter invoice-v2 und mit dem einfachen OQS_SIG_verify, das den leeren Kontext verwendet – beide Seiten müssen sich also auf den Kontext einigen. Eine gekürzte Signatur, ein 3-Byte-Blob und eine gültige Signatur über andere Daten lieferten alle dasselbe OQS_ERROR.

Die Entkapselung von ML-KEM meldet kein beschädigtes Chiffrat: Mit einem gekippten Bit gab OQS_KEM_decaps den Wert OQS_SUCCESS und ein anderes gemeinsames Geheimnis zurück, wie es die implizite Zurückweisung (Implicit Rejection) aus FIPS 203 verlangt. Die Abweichung zeigt sich erst, wenn die abgeleiteten Schlüssel verwendet werden, etwa als fehlgeschlagene AEAD-Entschlüsselung. Außerdem nimmt die Funktion keine Länge des Chiffrats entgegen und liest genau length_ciphertext Byte, bei ML-KEM-768 also 1088. Probiere beide Verfahren im ML-KEM-Tool und im Tool für Post-Quanten-Signaturen aus.

Fakten und die Prüfungen dahinter

Nichts im Folgenden ist aus einer Dokumentation abgeschrieben. Das Prüfskript content/libraries/verify/liboqs/run.sh hat liboqs (Open Quantum Safe) 0.16.0 am 20. Oktober 2026 im Container-Image debian:trixie-20261005-slim ausgeführt; die Seite muss mit seiner Ausgabe übereinstimmen, und jeder Fakt führt die zugehörigen Zeilen auf.

  • ECDSA-Kurven

    none

    Kein ECDSA: Jeder aktivierte Algorithmusbezeichner gehört zu einer Familie von Post-Quanten-Verfahren.

    Von der Prüfung aufgezeichnet
    fact ecdsa-curves = none
  • EdDSA

    none

    Kein EdDSA: liboqs implementiert ausschließlich Post-Quanten-Verfahren.

    Von der Prüfung aufgezeichnet
    fact eddsa = none
  • Post-Quanten-Algorithmen

    ML-KEMML-DSASLH-DSAFalconHQCClassic-McElieceFrodoKEMBIKENTRUsntrup761KyberMAYOCROSSUOVSNOVAMQOM

    Im Standard-Build durchlief je ein Parametersatz jeder aufgeführten Familie Schlüsselerzeugung, Kapselung oder Signieren und anschließend Entkapselung oder Prüfung.

    Von der Prüfung aufgezeichnet
    fact pqc = ML-KEM, ML-DSA, SLH-DSA, Falcon, HQC, Classic-McEliece, FrodoKEM, BIKE, NTRU, sntrup761, Kyber, MAYO, CROSS, UOV, SNOVA, MQOM
    evidence pqc: enabled: 41 KEMs, 221 signature schemes, 0 stateful signature schemes
    evidence pqc: enabled parameter sets by identifier prefix: ML-KEM- 3, ML-DSA- 3, SLH_DSA 156, Falcon- 4, HQC- 3, Classic-McEliece- 10, FrodoKEM- 6, eFrodoKEM- 6, BIKE- 3, NTRU- 6, sntrup 1, Kyber 3, MAYO- 4, cross- 18, OV- 12, SNOVA 12, mqom2 12
    evidence pqc: first parameter set of each family run end to end; failures: none
  • Zustandsbehaftete hashbasierte Signaturen

    not-built

    Im Standard-Build ist kein Parametersatz für XMSS oder LMS aktiviert.

    Von der Prüfung aufgezeichnet
    fact stateful-signatures = not-built
    evidence stateful-signatures: no XMSS or LMS parameter set is enabled in this build
  • ML-DSA-Signaturmodus

    hedged

    Zwei ML-DSA-65-Signaturen derselben Nachricht mit demselben Schlüssel unterschieden sich (Signieren im Hedged-Modus).

    Von der Prüfung aufgezeichnet
    fact ml-dsa-signing = hedged
    evidence ml-dsa-signing: ML-DSA-65: public key 1952 bytes, signature 3309 bytes; two signatures of one message are different
  • ML-DSA-Kontext-String

    supported

    Eine Signatur unter dem Kontext invoice-v1 bestand die Prüfung mit diesem Kontext und scheiterte mit invoice-v2 und mit dem leeren Kontext.

    Von der Prüfung aufgezeichnet
    fact ml-dsa-context-string = supported
    evidence ml-dsa-context-string: signed with context "invoice-v1": verifies with it yes, with "invoice-v2" no, with OQS_SIG_verify no
    evidence ml-dsa-context-string: an OQS_SIG_sign signature verifies with a zero-length context: yes
  • Fehlerhafte ML-DSA-Signatur

    returns-false

    Eine gekürzte Signatur, 3 Byte und eine falsche Nachricht lieferten alle OQS_ERROR (-1).

    Von der Prüfung aufgezeichnet
    fact ml-dsa-malformed-signature = returns-false
    evidence ml-dsa-malformed-signature: OQS_SIG_verify: truncated signature -1, 3 bytes -1, wrong message -1 (OQS_SUCCESS = 0, OQS_ERROR = -1)
  • Verändertes ML-KEM-Chiffrat

    implicit-rejection

    Mit einem gekippten Bit im Chiffrat gab OQS_KEM_decaps den Wert OQS_SUCCESS und ein anderes gemeinsames Geheimnis zurück.

    Von der Prüfung aufgezeichnet
    fact ml-kem-modified-ciphertext = implicit-rejection
    evidence ml-kem-modified-ciphertext: ML-KEM-768 (public key 1184, ciphertext 1088 bytes): one flipped bit, OQS_KEM_decaps returned 0 and the secrets differ
    evidence ml-kem-modified-ciphertext: kem.h: OQS_API OQS_STATUS OQS_KEM_decaps(const OQS_KEM *kem, uint8_t *shared_secret, const uint8_t *ciphertext, const uint8_t *secret_key)

Verwendung

Führe einen Schlüsselaustausch mit ML-KEM-768 durch und signiere und prüfe mit ML-DSA-65 unter einem Kontext-String.
#include <oqs/oqs.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
    OQS_init();
    /* ML-KEM-768: the receiver publishes pk, the sender encapsulates a fresh secret to it. */
    OQS_KEM *kem = OQS_KEM_new(OQS_KEM_alg_ml_kem_768);
    uint8_t *pk = malloc(kem->length_public_key), *sk = malloc(kem->length_secret_key);
    uint8_t *ct = malloc(kem->length_ciphertext), sent[32], received[32];
    OQS_KEM_keypair(kem, pk, sk);
    OQS_KEM_encaps(kem, ct, sent, pk);
    /* Decapsulation never reports a damaged ciphertext: it yields a different secret instead. */
    OQS_KEM_decaps(kem, received, ct, sk);
    printf("ML-KEM-768 secrets match: %d\n", memcmp(sent, received, 32) == 0);

    /* ML-DSA-65 with a FIPS 204 context string that ties the signature to one purpose. */
    OQS_SIG *sig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_65);
    uint8_t *vk = malloc(sig->length_public_key), *dk = malloc(sig->length_secret_key);
    uint8_t *s = malloc(sig->length_signature);
    const uint8_t msg[] = "order #1042 approved", ctx[] = "invoice-v1";
    size_t len = 0;
    OQS_SIG_keypair(sig, vk, dk);
    OQS_SIG_sign_with_ctx_str(sig, s, &len, msg, sizeof msg - 1, ctx, sizeof ctx - 1, dk);
    OQS_STATUS rc = OQS_SIG_verify_with_ctx_str(sig, msg, sizeof msg - 1, s, len, ctx, sizeof ctx - 1, vk);
    printf("ML-DSA-65 verified: %d (%zu-byte signature)\n", rc == OQS_SUCCESS, len);

    OQS_MEM_secure_free(sk, kem->length_secret_key);
    OQS_MEM_secure_free(dk, sig->length_secret_key);
    free(pk), free(ct), free(vk), free(s);
    OQS_KEM_free(kem), OQS_SIG_free(sig);
    OQS_destroy();
    return 0;
}

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

Einrichtung
apt-get -qq update >/dev/null && apt-get -qq install -y --no-install-recommends build-essential cmake ninja-build git ca-certificates libssl-dev >/dev/null 2>&1 && git clone -q --depth 1 --branch 0.16.0 https://github.com/open-quantum-safe/liboqs /oqs 2>/dev/null && test "$(git -C /oqs rev-parse HEAD)" = 5a1a854b0dc9f2141bdc771c555ee60c37950183 && cmake -S /oqs -B /oqs/build -G Ninja -DOQS_BUILD_ONLY_LIB=ON >/dev/null 2>&1 && ninja -C /oqs/build install >/dev/null
Befehl
cc -o usage usage.c -loqs -lcrypto && ./usage
Ausgabe muss passen (regulärer Ausdruck)
ML-KEM-768 secrets match: 1\nML-DSA-65 verified: 1 \(3309-byte signature\)

Bibliotheken