2026年:PQC密钥交换启动

文章讨论了后量子密码学(PQC)的迁移,特别是NIST推荐的ML-KEM和ML-DSA算法,用于替换现有的RSA和ECC密钥交换及数字签名方法。文章通过代码示例展示了如何在OpenSSL 3.5和Botan3库中集成ML-KEM,并对不同密钥交换方法的性能进行了基准测试,展示了ML-KEM在性能上与传统加密方法相当。

2026:PQC 密钥交换开始

我的 LinkedIn 信息流现在充满了“现在收集,稍后解密”的警告,而且看起来 2026 年将是新一轮网络安全警告的开始。对我来说,迁移到 PQC(后量子密码学)只是我们几十年来的自然迁移的一部分。

多年来,我们已经成功地迁移了我们的方法,例如从 Diffie-Hellman 方法的离散对数到椭圆曲线与 ECDH(椭圆曲线 Diffie-Hellman)的集成,以及 EDCSA 和 EdDSA 与可以替代 RSA 签名方法的签名方法的集成。在 TLS 1.2 之前,我们还可以使用 RSA 加密来传递加密密钥,但现在已经在 TLS 1.3 中被删除了(因为长期破解私钥可能会导致之前交换的所有密钥被泄露)。

迁移在密码学中是很自然的事情,尤其是很少有方法可以被定义为真正安全的 —— 只是在当前和不久的将来在计算上不可行。

因此,未来几年的关键重点将是发现我们现有的 RSA 和 ECC(椭圆曲线密码学)公钥方法的每一个应用之处,然后寻找这些方法的某种替代方案。NIST 提出的主要迁移路线是用 ML-KEM 替换我们的密钥交换方法(ECDH、X25519 和 RSA),并用 ML-DSA 替换我们的数字签名方法(RSA、ECDSA 和 EdDSA)。

ML-KEM

NIST 对正在开发的 PQC 标准进行了广泛的测试,并确保对新标准化方法的安全性和性能进行了适当的评估。

对于 ML-KEM,我们获取 Alice 的公钥,然后将其传递给 Bob。然后 Bob 将使用此密钥来封装密钥。其输出是 ctss。Bob 会将 ct 发送给 Alice,然后可以解码 ss 的值以显示共享密钥。然后 Alice 将解封装 ct 的值以显示共享密钥:

虽然 OpenSSL 3.5 现在集成了 PQC 方法,但 Botan3 库提供了与 C++ 代码的极佳集成。为此,我做了一个快速的 Botan3 基准测试,用于密钥交换/封装方法的每秒密钥生成数:

  • ECDH-secp256r1 (NIST P256) 19,021 keygen/sec
  • X25519 18,584 keygen/sec
  • ML-KEM-512 18,375 keygen/sec
  • ML-KEM-768 10,084 keygen/sec
  • X448 3,063 keygen/sec
  • DH-2048 655 keygen/sec
  • FrodoKEM-640-SHAKE 133 keygen/sec

对于 ECDH 和 X25519,ML-KEM 512 肯定与 NIST P256 曲线不相上下。ML-KEM-768 似乎是许多 PQC 设计人员的起点,因此其密钥生成明显慢于 ML-KEM-512。在 OpenSSL 3.5 中,我们集成了 [ 这里]:

##include <stdio.h>
##include <string.h>
##include <stdlib.h>

##include <openssl/evp.h>
##include <openssl/pem.h>
##include <openssl/err.h>
##include <openssl/core_names.h>
##include <openssl/params.h>
##include <openssl/ec.h>

static void hexdump(const char *label, const unsigned char *buf, size_t len) {
    printf("%s (%zu bytes): ", label, len);
    for (size_t i = 0; i < len; i++) printf("%02X", buf[i]);
    printf("\n");
}

static EVP_PKEY *generate_mlkem(unsigned char *type) {

    EVP_PKEY *pkey = NULL;

    EVP_PKEY_CTX *kctx = EVP_PKEY_CTX_new_from_name(NULL, type, NULL);

    EVP_PKEY_keygen_init(kctx);

    EVP_PKEY_keygen(kctx, &pkey);

 printf("Type: %s\n",type);

uint8_t pub[2592], priv[4896];
size_t priv_len, pub_len;

EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY,
                                priv, sizeof(priv), &priv_len);
EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PUB_KEY,
                                pub, sizeof(pub), &pub_len);

printf("Private key length: {%d}\n",priv_len);

hexdump("Private key (truncated to 500 bytes):",priv,500);

printf("\nPublic key length: {%d}\n",pub_len);
hexdump("\nPublic key(truncated to 500 bytes):",pub,500);

    EVP_PKEY_CTX_free(kctx);
    return pkey;
}

int main(int argc, char** argv) {

unsigned int pbitsize=1024;
unsigned int qbitsize=224;

    ERR_load_crypto_strings();
    OpenSSL_add_all_algorithms();

    unsigned char *type="ML-KEM-768";

    if (argc > 1) type  =  argv[1];

    EVP_PKEY *mlkem = generate_mlkem(type);

    return EXIT_SUCCESS;
}

就我个人而言,我认为与 Botan3 的集成提供了更好的集成 [ 这里]:

##include <botan/ml_kem.h>
##include <botan/hex.h>
##include <botan/pubkey.h>
##include <botan/system_rng.h>

##include <botan/pk_algs.h>
##include <botan/pk_keys.h>
##include <botan/pkcs8.h>
##include <botan/pubkey.h>
##include <botan/x509_key.h>

##include <iostream>

int main(int argc, char *argv[]){

 int mode =0;

 if (argc>0) mode = atoi( argv[1]);

       const size_t shared_key_len = 32;
        const std::string_view kdf = "HKDF(SHA-512)";

        Botan::System_RNG rng;

 auto m=Botan::ML_KEM_Mode::ML_KEM_768;

 if (mode==0) { m=Botan::ML_KEM_Mode::ML_KEM_512; std::cout  << "ML-KEM 512";}
 else if (mode==1) {m=Botan::ML_KEM_Mode::ML_KEM_768; std::cout  << "ML-KEM 768";}
 else  { m=Botan::ML_KEM_Mode::ML_KEM_1024; std::cout  << "ML-KEM 1024";}

        // Alice generates a keypair
 Botan::ML_KEM_PrivateKey priv_key(rng, m);

        auto pub_key = priv_key.public_key();

  // Encapsulate secret with Alice's public key
        const auto salt = rng.random_array<16>();
        Botan::PK_KEM_Encryptor enc(*pub_key, kdf);
        auto kem_result = enc.encrypt(rng, shared_key_len, salt);

        // Alice decapsulates using her private key
        Botan::PK_KEM_Decryptor dec(priv_key, rng, kdf);
        auto shared_alice = dec.decrypt(kem_result.encapsulated_shared_key(), shared_key_len, salt);

        std::cout << "\nBob's shared secret: "  << Botan::hex_encode(kem_result.shared_key(),true) << "\n";
        std::cout << "Alice's shared secret: "  << Botan::hex_encode(shared_alice, true) << "\n";

        auto ct = Botan::hex_encode(kem_result.encapsulated_shared_key());

        std::cout << "\nCiphertext (first 64 bytes out of " << ct.length() << "): " << ct.substr(0, 128)  << "\n";

        std::cout << "\nAlice's private key:\n" << Botan::PKCS8::PEM_encode(priv_key) << "\n";
        std::cout << "\nAlice's public key:\n"  << Botan::X509::PEM_encode(*pub_key) << "\n";

        const auto priv_bytes = priv_key.private_key_bits();
        const auto pub_bytes  = pub_key->public_key_bits();
        std::cout << "\nAlice's private key size: " << priv_bytes.size() << "\n";
        std::cout << "\nAlice's public key size: "  << pub_bytes.size() << "\n";

   return 0;
}

一个示例运行显示了封装和解封装过程:

例如,对于 ML-KEM-512:

ML-KEM 512
Bob's shared secret: 3BF1FAE112317B6A2B9CF4C691B87C28075B729DAF9F8B3A860D43D4E83D3BD3
Alice's shared secret: 3BF1FAE112317B6A2B9CF4C691B87C28075B729DAF9F8B3A860D43D4E83D3BD3

Ciphertext (first 64 bytes out of 1536): E30B9ABEA61B0FD5BCE420E563393B53728DB8228496C0C3878C83926EF0A9915F6F5E8F99429FB70F68131417124C5BE1A59CA6FC3ED7F5B357D3E10A98B9A7
Alice's private key:
-----BEGIN PRIVATE KEY-----
MFICAQAwCwYJYIZIAWUDBAQBBECBzqGuEj6eR5qgQtHqAgOyeY1mXEjNd6SKBQhg
pC/tGFJybf0DoVLpnV8kS9hob4dtdw1wKcQINBk1KJBgHzWv
-----END PRIVATE KEY-----

Alice's public key:
-----BEGIN PUBLIC KEY-----
MIIDMjALBglghkgBZQMEBAEDggMhAIaBHjB1iOjFP47lkf0BPkiibhlkYdQGVgVB
qK7Jt0d2oXgTZ3YGIvnbhy0DPZDADKsHGa5gqAKcgydIzMmFCg57lAQ5YNuldTiB
i7vYgHlHEdpIAad5Lr53QhH8CXF1e+80IsBzXPnFot8RoFCghhVrdGXbI3nanPwa
QO5LCrwZsyeaf/SnzNlbbSaoyglpoMMjvjJSAO6ZikcmzdAapdapQ3bXLhUpvmQT
GWikJcKXv8TwY8ObinriX1ckpoX6yZqVnAL1WBwIzEb2FcRYksr3hOh5D9rnTEN1
WHG8HkPjKGGVUVMMzjhTtRo7VYF7chvaKu0pWm+sIUo7hCqazHsSE38qyBMbyawW
iAGREeDaT8knvYxKFn4TF7y0t4psup1YJFxXvnS7DEN6Do1zZO23E4R5Iti3qESl
k6PQzsoBAbpoqSLAyDdlPUcIlDvTbrCSVsPQhV3xQn3IYUdIKq9ha4kzzkeiSoOT
L38ljz95Or0hSvxcxX4Egj2cmUPZHctpL+/FQrUWhpIMXewMcFAalnqbdJF7p2lU
RftlkOLcuMBam9aJV2qGDmpXcdrViKTVKMURVz+BPJUJToPzUqCHF95DYHVhjO5w
EEeaFFgbEbrgUwpKKBvoCZ62ekfrSxMDq3FxSGIBLsrasPeARZ6GGA4mGmAcTxhj
uyq3VPdcJTbysvUwOlIru261qu3qhna2XXDiHGlbMZ8ZWdeMG+kbb/aLVsQISTqb
UJ6oFdq5VlYwfwwxurQwwbYpAiqnbd4WiJblwuPWtpFnEszTcHPXm2QLX9sjTkuH
OzV7BT2gWFc7XqcLSa1yslTMO2ZCgeEEtIVyuptQZ4oQBRw0VID1yHjpQFzRRa/o
ZyPlptUgTULEPCriM93SwskHV+24WY+npgY3P7HhuhP5mHgybmLyww8aiZPhvm08
BG4VUpo1cn1pttZ8yUtqVLfSq3JBiUosXCAESGGCLfu6ddypeQt4atEjnI0Tp6cy
lRurJWYxzaPDeas0IN/DHSTpR+YIPGuWFcnQFgi8Khmz1gi28doQC0q37+Ur31JW
iQCqj4qG
-----END PUBLIC KEY-----

Alice's private key size: 64
Alice's public key size: 800

结论

2026 年,它开始了!

OpenSSL 的集成在这里:

https://asecuritysite.com/openssl/index

以及 Botan3:

https://asecuritysite.com/botan3/

  • 原文链接: billatnapier.medium.com/...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
billatnapier
billatnapier
江湖只有他的大名,没有他的介绍。