1. PQC算法库选型与集成环境搭建

PQC算法库选型与集成环境搭建 学习卡片

为什么选型要先于写代码

PQC 算法库的差异不只在算法实现本身,还体现在 API 风格、许可证、构建系统、平台支持与是否提供 KEM 高层封装。选错库会导致后续封装层反复重写。本例以“跑通首个 KEM 握手”为验收目标,对三类主流实现做横向对比后完成环境搭建。

三类主流实现对比

实现定位API 风格许可证平台支持集成成本
liboqs算法聚合库 + 高层 KEM/SIG APIC,OQS_KEM 对象式MITLinux/macOS/Windows,CMake低,开箱即用
PQClean纯净参考实现集合C,按算法独立目录,无统一高层 APICC0 / 各算法自带跨平台,Makefile/CMake中,需自行封装
BoringSSL+OQS在 TLS 栈中启用 PQC 混合握手EVP_PKEY / SSL_CTX 扩展OpenSSL 系 + OQS 补丁Linux/macOS 为主高,需打补丁并重编
选型结论:本例目标是“快速跑通 KEM 握手并保留后续封装空间”,liboqs 提供统一的 OQS_KEM 抽象,接口稳定、许可证宽松、构建简单,作为首选;PQClean 适合需要审计算法源码的场景;BoringSSL+OQS 适合最终要落到 TLS 握手的集成阶段。

选型决策关系

选型目标 跑通 KEM 握手 + 可封装 评估维度 API 统一性 · 许可证 · 平台 · 构建成本 liboqs OQS_KEM 统一对象 MIT · CMake Linux/macOS/Win ✓ 本例选用 PQClean 按算法独立目录 CC0 · 无高层 API 需自行封装 适合源码审计 BoringSSL+OQS EVP_PKEY / SSL_CTX 需打补丁重编 集成成本高 适合 TLS 落地阶段 环境搭建 CMake 构建 + 安装 链接 liboqs → 首个 KEM 握手

环境搭建与首个 KEM 握手

以下步骤在 Linux/macOS 上验证,使用 liboqs 的 CMake 构建流程。先安装依赖并编译安装库,再编写一个最小 KEM 握手程序。

# 1. 获取源码
git clone --depth 1 https://github.com/open-quantum-safe/liboqs.git
cd liboqs && mkdir build && cd build

# 2. 配置并编译(关闭不需要的算法可加速构建)
cmake -GNinja -DCMAKE_INSTALL_PREFIX=$HOME/liboqs-install \
      -DOQS_BUILD_ONLY_LIB=ON -DOQS_USE_OPENSSL=ON ..
ninja && ninja install

# 3. 验证安装
ls $HOME/liboqs-install/lib/liboqs.*
ls $HOME/liboqs-install/include/oqs/

接着编写最小 KEM 握手示例,使用 Kyber512 完成密钥生成、封装与解封装,并校验双方共享密钥一致。

#include <stdio.h>
#include <string.h>
#include <oqs/oqs.h>

int main(void) {
    OQS_KEM *kem = OQS_KEM_new(OQS_KEM_alg_kyber_512);
    if (kem == NULL) { printf("KEM 不可用\n"); return 1; }

    uint8_t *pk  = malloc(kem->length_public_key);
    uint8_t *sk  = malloc(kem->length_secret_key);
    uint8_t *ct  = malloc(kem->length_ciphertext);
    uint8_t *ss1 = malloc(kem->length_shared_secret);
    uint8_t *ss2 = malloc(kem->length_shared_secret);

    /* 接收方生成密钥对 */
    OQS_KEM_keypair(kem, pk, sk);

    /* 发送方用公钥封装,得到密文与共享密钥 ss1 */
    OQS_KEM_encaps(kem, ct, ss1, pk);

    /* 接收方用私钥解封装,恢复共享密钥 ss2 */
    OQS_KEM_decaps(kem, ss2, ct, sk);

    printf("共享密钥一致: %s\n",
           memcmp(ss1, ss2, kem->length_shared_secret) == 0 ? "是" : "否");

    OQS_MEM_secure_free(sk, kem->length_secret_key);
    OQS_MEM_secure_free(ss1, kem->length_shared_secret);
    OQS_MEM_secure_free(ss2, kem->length_shared_secret);
    free(pk); free(ct);
    OQS_KEM_free(kem);
    return 0;
}

编译并运行:

gcc kem_demo.c -o kem_demo \
    -I$HOME/liboqs-install/include \
    -L$HOME/liboqs-install/lib -loqs -lcrypto
LD_LIBRARY_PATH=$HOME/liboqs-install/lib ./kem_demo
# 预期输出:共享密钥一致: 是
若链接时报 undefined reference to OQS_KEM_new,检查 -loqs 是否在源文件之后;若运行时报找不到动态库,设置 LD_LIBRARY_PATH(macOS 用 DYLD_LIBRARY_PATH)。

验收清单

  • liboqs 编译安装成功,liboqs.so 与 oqs/oqs.h 存在。
  • Kyber512 的 OQS_KEM_new 返回非空,说明算法已启用。
  • 封装与解封装得到的共享密钥 memcmp 为 0。
  • 私钥与共享密钥使用 OQS_MEM_secure_free 清零释放。