mlkem测试后量子密钥交换
如果你要在 Go 里试用后量子密钥交换,先记住一个边界:crypto/mlkem 负责真正的 ML-KEM 密钥封装,crypto/mlkem/mlkemtest 只给测试提供去随机封装。前者用于建立共享密钥,后者用于让同一组测试输入得到可重复的密文和共享密钥。
Go 1.24 起标准库提供 ML-KEM-768 和 ML-KEM-1024。本文以官方更建议多数应用优先考虑的 ML-KEM-768 为例,串起生成密钥、公开封装密钥、封装、解封装和测试隔离。
一句话结论:生产代码调用GenerateKey768、Encapsulate、Decapsulate;需要固定输入做 known-answer test 时,再把mlkemtest.Encapsulate768放进测试文件,绝不要把它当成生产封装入口。
先把 Go 版本和 ML-KEM 的角色对齐
crypto/mlkem 是密钥封装机制(KEM),它的结果是共享密钥与密文,不是直接接收业务明文的加密器。典型协议是:接收端生成密钥对,只把封装公钥发给发送端;发送端根据公钥封装出密文和共享密钥;接收端用私钥和密文恢复同一共享密钥,后续再把共享密钥交给 AEAD 或密钥派生流程。
官方资料:https://pkg.go.dev/crypto/mlkem、https://pkg.go.dev/crypto/mlkem/mlkemtest、https://go.dev/doc/go1.24。
如果项目仍低于 Go 1.24,导入 crypto/mlkem 会直接失败。不要为了绕过编译错误随意换成同名第三方包;先把工具链和 go.mod 的最低版本边界说清楚。

用 ML-KEM-768 完成一次共享密钥建立
下面的示例把 Alice 视为持有解封装私钥的一方,把 Bob 视为拿到公开封装密钥的一方。Bob 只需要发送密文,双方最终比较得到的 32 字节共享密钥。
package main
import (
"bytes"
"crypto/mlkem"
"fmt"
)
func establishSharedKey() error {
// 接收端生成 ML-KEM-768 私钥,并从私钥导出可公开发送的封装公钥。
dk, err := mlkem.GenerateKey768()
if err != nil {
return fmt.Errorf("生成 ML-KEM-768 密钥失败:%w", err)
}
publicBytes := dk.EncapsulationKey().Bytes()
// 发送端只解析封装公钥;私钥不会离开接收端。
ek, err := mlkem.NewEncapsulationKey768(publicBytes)
if err != nil {
return fmt.Errorf("解析封装公钥失败:%w", err)
}
senderKey, ciphertext := ek.Encapsulate() // 生产路径使用安全随机源。
// 接收端用私钥解封装;长度错误会返回 error,不能忽略。
receiverKey, err := dk.Decapsulate(ciphertext)
if err != nil {
return fmt.Errorf("解封装失败:%w", err)
}
if !bytes.Equal(senderKey, receiverKey) {
return fmt.Errorf("两端共享密钥不一致")
}
fmt.Printf("shared key=%d bytes, ciphertext=%d bytes\n", len(senderKey), len(ciphertext))
return nil
}
func main() {
if err := establishSharedKey(); err != nil {
panic(err) // 示例把错误交给顶层;服务代码应返回并记录上下文。
}
}
ML-KEM-768 的共享密钥是 32 字节,封装公钥是 1184 字节,密文是 1088 字节。这里的尺寸适合放进协议设计和传输预算,但不要把“字节数正确”当成密钥有效性的唯一判断;解封装仍应检查返回的错误,并在协议层处理身份认证和重放问题。
用 mlkemtest 写可重复测试
生产封装会从安全随机源取数,同一个公钥每次得到的密文通常不同。测试若只断言“能解封装”,可以直接使用生产 API;若要复现标准测试向量或定位实现差异,则需要固定封装阶段的随机输入。官方的 mlkemtest.Encapsulate768 接受 32 字节随机输入,并明确限制为 known-answer tests。

package mlkem_test
import (
"bytes"
"crypto/mlkem"
"crypto/mlkem/mlkemtest"
"testing"
)
func TestMLKEM768DeterministicEncapsulation(t *testing.T) {
// 固定测试向量只用于测试;生产代码不能复用固定随机输入。
seed := bytes.Repeat([]byte{0x27}, mlkem.SeedSize)
random := bytes.Repeat([]byte{0x42}, 32) // mlkemtest 要求 32 字节封装随机输入。
dk, err := mlkem.NewDecapsulationKey768(seed)
if err != nil {
t.Fatalf("构造测试私钥失败:%v", err)
}
ek := dk.EncapsulationKey()
shared1, ciphertext1, err := mlkemtest.Encapsulate768(ek, random)
if err != nil {
t.Fatalf("第一次去随机封装失败:%v", err)
}
shared2, ciphertext2, err := mlkemtest.Encapsulate768(ek, random)
if err != nil {
t.Fatalf("第二次去随机封装失败:%v", err)
}
if !bytes.Equal(shared1, shared2) || !bytes.Equal(ciphertext1, ciphertext2) {
t.Fatal("固定测试输入没有得到稳定结果")
}
decoded, err := dk.Decapsulate(ciphertext1)
if err != nil {
t.Fatalf("测试密文解封装失败:%v", err)
}
if !bytes.Equal(shared1, decoded) {
t.Fatal("封装与解封装得到的共享密钥不一致")
}
}
示例中的固定种子只是为了展示测试 API 的边界;正式 known-answer test 应替换成项目维护的、来源明确的测试向量,并把期望密文和共享密钥也写入断言。不要因为测试需要可重复,就把固定字节数组带到线上代码里。
检查错误、长度和密钥生命周期
排查 ML-KEM 测试失败时,我会按三层看:第一层是工具链是否至少为 Go 1.24;第二层是封装公钥是否由同一参数集解析,例如 768 的公钥不能交给 1024 的解析函数;第三层是密文长度和解封装错误是否被保留。官方文档说明,长度不正确的密文会返回错误;长度正确但内容无效时,解封装可能返回一个与发送端不匹配的共享密钥,因此协议还需要认证或失败检测。
- 不要打印私钥、共享密钥或完整密文;日志只记录阶段和长度。
- 不要把
mlkemtest的固定随机输入用于生产。 - 不要只比较公钥、密文长度就判定交换成功,最终要比较双方共享密钥或进入经过认证的后续协议。
- 如果需要和 TLS 对接,应单独研究 Go 的混合后量子握手能力,不要把裸 ML-KEM API 直接当成 TLS 配置。
一张表记住生产和测试的分工
| 目标 | 推荐 API | 随机性 | 放置位置 |
|---|---|---|---|
| 线上建立共享密钥 | GenerateKey768、Encapsulate、Decapsulate | 使用安全随机源 | 生产包 |
| 复现封装结果 | mlkemtest.Encapsulate768 | 固定 32 字节测试输入 | 测试文件 |
| 检查协议边界 | 长度、错误、共享密钥比较 | 不记录秘密值 | 测试与运行日志 |
最后再强调一次:ML-KEM 的职责是协商共享密钥。真正保护业务数据时,还要把密钥交给合适的认证加密或密钥派生组件,并为对端身份、协议版本和失败重试设计独立的约束。
常见问题
Go 1.23 能直接导入 crypto/mlkem 吗?
不能。这个标准库包从 Go 1.24 开始提供,项目应先升级工具链或明确采用其他经过评估的实现。
mlkemtest 可以放在业务代码里做固定密钥交换吗?
不建议。它的文档用途是 known-answer tests;业务代码应使用生产 API 的安全随机封装。
为什么密文长度正确仍可能得到不同共享密钥?
ML-KEM 的解封装对“长度正确但内容无效”的密文可能产生不匹配的共享密钥,而不是必然返回错误。协议必须把认证和结果一致性纳入整体设计。
tls加密客户端Hello握手
- 上一篇
- tls加密客户端Hello握手
- 下一篇
- testingCryptotest测试随机性
-
- Golang · Go教程 | 16分钟前 |
- slog为请求添加结构化上下文
- 349浏览 收藏
-
- Golang · Go教程 | 16分钟前 | 标准库 · 单元测试 · Go教程 · Go crypto/rand testing/cryptotest SetGlobalRandom 确定性测试
- testingCryptotest测试随机性
- 339浏览 收藏
-
- Golang · Go教程 | 24分钟前 | 标准库 · TLS · 网络安全 · Go教程 · tls Go crypto/tls 握手 证书校验 ClientHello
- tls加密客户端Hello握手
- 216浏览 收藏
-
- Golang · Go教程 | 24分钟前 |
- cryptoHPKE封装会话密钥
- 392浏览 收藏
-
- Golang · Go教程 | 27分钟前 | go · net/http · Go http/2 HTTP/1 http.Protocols
- httpProtocols配置HTTP协议集合
- 147浏览 收藏
-
- Golang · Go教程 | 28分钟前 |
- Go os.Root Symlink 怎样创建受限目录内的相对链接
- 451浏览 收藏
-
- Golang · Go教程 | 32分钟前 |
- cmpOr为配置提供第一个非零值
- 484浏览 收藏
-
- Golang · Go教程 | 34分钟前 | 标准库 · Go教程 · Go Float64Histogram runtime/metrics Buckets Counts 百分位
- Go runtime/metrics 怎样用直方图桶估算百分位
- 203浏览 收藏
-
- Golang · Go教程 | 37分钟前 | 日志 · zap · 性能优化 · Go教程 · Go 结构化日志 Logger.With go.uber.org/zap zap.Logger Logger.WithLazy
- Go zap.Logger 复用上下文字段并降低日志分配
- 474浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 1032次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 1032次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 1175次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 1136次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 978次使用
-
- GScript 编写标准库示例详解
- 2022-12-30 369浏览
-
- 一文详解Go语言单元测试的原理与使用
- 2022-12-29 377浏览
-
- 关于Golang标准库flag的全面讲解
- 2023-02-25 344浏览
-
- Golang 单元测试和基准测试实例详解
- 2022-12-23 275浏览
-
- Golang标准库unsafe源码解读
- 2022-12-29 464浏览

