本文介绍了ML-KEM(Module-Learning Key Encapsulation Mechanism),一种后量子密码学中的密钥封装方法,旨在替代传统的Diffie-Hellman密钥交换。文章通过逐步指南,阐述了ML-KEM的原理,包括密钥生成、封装和解封装过程,并提供了使用wolfCrypt库进行ML-KEM-512实现的示例代码。
在技术领域,每隔一段时间,就会出现一些改变整个领域的东西。后量子密码学现在就属于这种情况,我们将删除 RSA 和 ECC 公钥密码学领域的教学内容,并用量子稳健的方法取而代之。其中一个将被淘汰的领域是 Diffie-Hellman 密钥交换方法的使用。它现在已经有大约 49 年的历史,并且一直做得很好,但是需要用 KEM(密钥封装方法)代替。基本上,KEM 更像是公钥加密,而不是密钥交换方法。
如果你从事网络安全工作,你可能已经了解了神奇的 Diffie-Hellman 方法。使用此方法,Bob 和 Alice 各自创建一个密钥(分别为 b 和 a),然后共享其密钥的公共版本:
最后,他们可以生成相同的密钥。对于 ML-KEM(又名 Kyber),我们获取 Alice 的公钥,然后将其传递给 Bob。然后,Bob 将使用此密钥来封装密钥。此操作的输出是 ct 和 ss。Bob 会将 ct 发送给 Alice,然后可以解码 ss 的值以显示共享密钥。然后,Alice 将解封装 ct 的值以显示共享密钥:
使用 wolfCrypt,最初,Alice 将创建一个密钥对:
// Alice creates a key pair
printf("Alice creates an ML-KEM-512 key pair\n\n");
ret = wc_InitRng(&rng);
ret = wc_MlKemKey_Init(&AliceKey, WC_ML_KEM_512,0, INVALID_DEVID);
int ss_size;
wc_KyberKey_SharedSecretSize(&AliceKey, &ss_size);
ret = wc_MlKemKey_MakeKey(&AliceKey, &rng);
这将包含一个公钥和一个私钥。然后,她可以为 Bob 编码公钥:
byte Alicepub[WC_ML_KEM_512_PUBLIC_KEY_SIZE];
ret = wc_MlKemKey_EncodePublicKey(&AliceKey, Alicepub, WC_ML_KEM_512_PUBLIC_KEY_SIZE);
AlicePub 的字节数组将包含她的编码后的公钥,她将发送给 Bob。然后,Bob 可以解码此公钥并将其放入 AliceKey 中
ret = wc_MlKemKey_DecodePublicKey(&AliceKey, Alicepub, WC_ML_KEM_512_PUBLIC_KEY_SIZE);
使用 Alice 的公钥,Bob 将生成密文,该密文封装共享密钥:
byte ct[WC_ML_KEM_512_CIPHER_TEXT_SIZE], ss[WC_ML_KEM_512_CIPHER_TEXT_SIZE];
ret = wc_MlKemKey_Encapsulate(&AliceKey, ct, ss, &rng);
然后,他可以将密文 ( ct) 发送给 Alice。然后,Alice 可以使用以下命令显示共享密钥 ( sharedsecretAlice):
ret = wc_MlKemKey_Decapsulate(&AliceKey,ct, shared_secretAlice, &rng);
Bob 应该使用以下命令获得相同的共享密钥:
wc_MlKemKey_DecodePrivateKey(&AliceKey, shared_secretBob,&ss_size);
以下定义了 Kyber、SABER、NTRU 和 McEliece 的密钥大小:
Type Public key size (B) Secret key size (B) Ciphertext size (B)
------------------------------------------------------------------------
ML-KEM-512 800 1,632 768 Learning with errors (Lattice)
ML-KEM-738 1,184 2,400 1,088 Learning with errors (Lattice)
ML-KEM-1024 1,568 3,168 1,568 Learning with errors (Lattice)
LightSABER 672 1,568 736 Learning with rounding (Lattice)
SABER 992 2,304 1,088 Learning with rounding (Lattice)
FireSABER 1,312 3,040 1,472 Learning with rounding (Lattice)
McEliece348864 261,120 6,452 128 Code based
McEliece460896 524,160 13,568 188 Code based
McEliece6688128 1,044,992 13,892 240 Code based
McEliece6960119 1,047,319 13,948 226 Code based
McEliece8192128 1,357,824 14,120 240 Code based
NTRUhps2048509 699 935 699 Lattice
NTRUhps2048677 930 1,234 930 Lattice
NTRUhps4096821 1,230 1,590 1,230 Lattice
SIKEp434 330 44 346 Isogeny
SIKEp503 378 56 402 Isogeny
SIKEp751 564 80 596 Isogeny
SIDH 564 48 596 Isogeny
此代码位于 [ 这里]:
##include <stdio.h>
##include <stdlib.h>
##include <stdint.h>
##include <wolfssl/wolfcrypt/mlkem.h>
##include <wolfssl/wolfcrypt/wc_mlkem.h>
##include <wolfssl/wolfcrypt/random.h>
char* to_hex_string(const unsigned char* array, size_t length)
{
char* outstr = malloc(2 * length + 1);
if (!outstr) return outstr;
char* p = outstr;
for (size_t i = 0; i < length; ++i) {
p += sprintf(p, "%02hhx", array[i]);
}
return outstr;
}
int main(int argc, char** argv)
{
MlKemKey AliceKey;
int ret = 0;
WC_RNG rng;
// Alice creates a key pair
printf("Alice creates an ML-KEM-512 key pair\n\n");
ret = wc_InitRng(&rng);
ret = wc_MlKemKey_Init(&AliceKey, WC_ML_KEM_512,0, INVALID_DEVID);
int ss_size;
wc_KyberKey_SharedSecretSize(&AliceKey, &ss_size);
ret = wc_MlKemKey_MakeKey(&AliceKey, &rng);
byte Alicepub[WC_ML_KEM_512_PUBLIC_KEY_SIZE];
ret = wc_MlKemKey_EncodePublicKey(&AliceKey, Alicepub, WC_ML_KEM_512_PUBLIC_KEY_SIZE);
// Bob receives the key
printf("Bob receives public key (size=%d) [displaying first 100 bytes]: %s\n\n", WC_ML_KEM_512_PUBLIC_KEY_SIZE, to_hex_string(Alicepub, 200));
ret = wc_MlKemKey_DecodePublicKey(&AliceKey, Alicepub, WC_ML_KEM_512_PUBLIC_KEY_SIZE);
byte ct[WC_ML_KEM_512_CIPHER_TEXT_SIZE], ss[WC_ML_KEM_512_CIPHER_TEXT_SIZE];
ret = wc_MlKemKey_Encapsulate(&AliceKey, ct, ss, &rng);
int len = WC_ML_KEM_512_CIPHER_TEXT_SIZE;
printf("Bob Encapsulates secret (Size=%d) [displaying first 100 bytes]: %s\n\n",len, to_hex_string(ct,200));
byte shared_secretAlice[WC_ML_KEM_512_CIPHER_TEXT_SIZE];
// Alice receives ct
ret = wc_MlKemKey_Decapsulate(&AliceKey,ct, shared_secretAlice, &rng);
printf("Alice Decapsulated Shared Secret: %s\n\n", to_hex_string(shared_secretAlice, ss_size));
// Bob determines Shared Secret
byte shared_secretBob[WC_ML_KEM_512_PRIVATE_KEY_SIZE];
wc_MlKemKey_DecodePrivateKey(&AliceKey, shared_secretBob,&ss_size);
printf("Bob Secret Share (Recovered): %s\n\n", to_hex_string(shared_secretBob, ss_size));
wc_MlKemKey_Free(&AliceKey);
return 0;
}
一个示例运行 [ 这里]:
Alice creates an ML-KEM-512 key pair
Bob receives public key (size=800) [displaying first 100 bytes]: 44b5732a66c56460839dab1324502bf72c6b3c7963f2985928fcb88d8762452517d20077d912ac72d4a28f084a2981a968e440ce08973fd81738a80dfe207d9ada8442aa937a222633b623fd294a2b5a9effca5c020063472b1c441651bb50c199031041016dbd683e6e92243a6a916a9c5aaf2ca8c5d1ca62617eeae8ada3f226928a68e0562345d544a55811c7443250e418f74604da113a1579a67ed97e59e03b463080206356875647e83c6787a53c3d5920d984ce5d35631b0c2a12e73c2009a96d244244f7
Bob Encapsulates secret (Size=768) [displaying first 100 bytes]: 15c34de118e9a63af1567ede7a0ecf75a158e25826916ce0ce4a32e98cd8e4e2d6b287c4a47f9c43ea81d6e72ffad8e0cf5a6a34e80f950ed05b8b8e89bdbf96268fa673575da47da2b90200774ed44ee8e7d5d4987e96749524b56565b0f172447f9637b8358d87044fec0cdbbfe11cbf932ff566a2b452aa622361cd5f5d1528bbdec7f6632cb96a8e539e1092f534bddc658e419ea13939f2260757ddec871fad7276a6481b56733ddf3e43c1b78aaffc27b1152aaf896f3c66f61dd4b3115d201f77c5b421a2
Alice Decapsulated Shared Secret: eac883ac387604b9d07187a9ae91fc4889fb2439a01168775987a19af5477185
Bob Secret Share (Recovered): eac883ac387604b9d07187a9ae91fc4889fb2439a01168775987a19af5477185
因此,与 ECDH 说声再见,并向 ML-KEM 问好。
- 原文链接: billatnapier.medium.com/...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!