跳到主要内容
ecdsa.com
C

liboqs (Open Quantum Safe)

liboqs,Open Quantum Safe 项目的后量子 KEM 与签名 C 库:通过同一套 API 提供 ML-KEM、ML-DSA 和 SLH-DSA,以及一长串候选算法——用作者的话说,它面向研究和原型开发。
许可证
MIT
检查的版本
0.16.0 ·
源代码
github.com/open-quantum-safe/liboqs
文档
openquantumsafe.org/liboqs/

兼容性概览

后量子

EdDSA
none
后量子算法
ML-KEMML-DSASLH-DSAFalconHQCClassic-McElieceFrodoKEMBIKENTRUsntrup761KyberMAYOCROSSUOVSNOVAMQOM

liboqs 通过同一套 C API 汇集了后量子密钥封装机制(OQS_KEM)和签名方案(OQS_SIG)的实现,也是 OpenSSL 3 的 Open Quantum Safe 提供程序的引擎。本页的事实基于 0.16.0 版(提交 5a1a854b0dc9)检查得出,构建时使用默认的 CMake 选项,即由 OpenSSL 提供对称原语。README 用全大写英文写着:“我们目前不建议在生产环境中依赖此库,也不建议用它保护任何敏感数据。”如需在生产环境中使用 ML-KEM 和 ML-DSA,可以参阅 OpenSSL、BoringSSL、AWS-LC 和 Bouncy Castle 页面,其中列出了它们的主 API 提供哪些算法。

默认构建启用了 41 个 KEM 和 221 个签名参数集,每个算法族都有一个参数集完成了完整的往返测试:NIST 标准 ML-KEM、ML-DSA 和 SLH-DSA(156 个 SLH-DSA 变体,包括纯模式和预哈希模式),Falcon,KEM 候选算法 HQC、Classic McEliece、FrodoKEM、BIKE、NTRU 和 sntrup761,标准化之前的 Kyber,以及附加签名候选算法 MAYO、CROSS、UOV、SNOVA 和 MQOM。新代码中应使用 ML-KEM-768 这个名称,而不是 Kyber768。默认构建没有启用任何 XMSS 或 LMS 参数集。

ML-DSA 签名采用对冲方式:用同一密钥对同一消息生成的两个签名不同,因此测试必须验证签名,而不能比较字节。FIPS 204 上下文字符串通过 OQS_SIG_sign_with_ctx_str 支持;在上下文 invoice-v1 下生成的签名,用 invoice-v2 验证失败,改用普通的 OQS_SIG_verify(它使用空上下文)验证也失败,因此双方必须约定同一个上下文。截断的签名、3 字节的数据块,以及针对其他数据的有效签名,返回的都是同一个 OQS_ERROR。

ML-KEM 解封装不会报告密文损坏:密文翻转一位后,OQS_KEM_decaps 返回 OQS_SUCCESS 和一个不同的共享密钥,这正是 FIPS 203 的隐式拒绝所要求的。只有在使用派生出的密钥时才会暴露不匹配,例如表现为 AEAD 解密失败。该函数也不接收密文长度参数,而是恰好读取 length_ciphertext 字节,ML-KEM-768 为 1088 字节。可以在 ML-KEM 工具和后量子签名工具中试用这两种方案。

事实及其依据的检查

以下内容均非抄自文档。检查脚本 content/libraries/verify/liboqs/run.sh 于2026年10月20日在容器镜像 debian:trixie-20261005-slim 中运行了 liboqs (Open Quantum Safe) 0.16.0;本页内容必须与它的输出一致,每条事实都列出了对应的输出行。

  • ECDSA 曲线

    none

    不支持 ECDSA:所有已启用的算法标识符都属于后量子算法族。

    检查记录
    fact ecdsa-curves = none
  • EdDSA

    none

    不支持 EdDSA:liboqs 只实现后量子方案。

    检查记录
    fact eddsa = none
  • 后量子算法

    ML-KEMML-DSASLH-DSAFalconHQCClassic-McElieceFrodoKEMBIKENTRUsntrup761KyberMAYOCROSSUOVSNOVAMQOM

    在默认构建中,所列每个算法族都有一个参数集完成了密钥生成、封装或签名,以及解封装或验证。

    检查记录
    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
  • 有状态哈希签名

    not-built

    默认构建没有启用任何 XMSS 或 LMS 参数集。

    检查记录
    fact stateful-signatures = not-built
    evidence stateful-signatures: no XMSS or LMS parameter set is enabled in this build
  • ML-DSA 签名模式

    hedged

    用同一密钥对同一消息生成的两个 ML-DSA-65 签名不同(对冲签名)。

    检查记录
    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 上下文字符串

    supported

    在上下文 invoice-v1 下生成的签名,用该上下文验证通过,用 invoice-v2 和空上下文验证均失败。

    检查记录
    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
  • 格式错误的 ML-DSA 签名

    returns-false

    截断的签名、3 字节数据和错误的消息都返回 OQS_ERROR(-1)。

    检查记录
    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)
  • 被修改的 ML-KEM 密文

    implicit-rejection

    密文翻转一位后,OQS_KEM_decaps 返回 OQS_SUCCESS 和一个不同的共享密钥。

    检查记录
    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)

用法

执行一次 ML-KEM-768 密钥交换,并在上下文字符串下用 ML-DSA-65 签名和验证。
#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;
}

代码片段测试工具会在容器镜像 debian:trixie-20261005-slim 中原样运行每个示例,只要输出不匹配,运行就会失败。

环境准备
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
命令
cc -o usage usage.c -loqs -lcrypto && ./usage
输出必须匹配(正则表达式)
ML-KEM-768 secrets match: 1\nML-DSA-65 verified: 1 \(3309-byte signature\)

库