Go 1.27 的 ML-DSA:crypto/mldsa、TLS 1.3 签名方案与 MLKEM1024 配置
Go 1.27(2026-08-19 发布)把后量子签名直接放进了标准库:新增 crypto/mldsa 实现 FIPS 204 的 ML-DSA,crypto/x509 能处理 ML-DSA 的公钥、私钥与签名,crypto/tls 则把 ML-DSA 接进了 TLS 1.3 的签名方案协商。密钥交换一侧,MLKEM1024 也可以通过 Config.CurvePreferences 显式配置了。
发布说明:
发布博客:
crypto/mldsa:FIPS 204 的 ML-DSA
新包 crypto/mldsa 提供 ML-DSA 的签名与验签,算法定义来自 FIPS 204。使用方式与标准库里其他签名包一致:生成或加载密钥,对消息签名,再验签。
import "crypto/mldsa"
priv, err := mldsa.GenerateKey(mldsa.MLDSA65) // 参数集:MLDSA44 / MLDSA65 / MLDSA87
if err != nil {
return err
}
sig, err := mldsa.Sign(priv, msg)
if err != nil {
return err
}
ok := mldsa.Verify(priv.PublicKey(), msg, sig)
三个参数集在安全强度与尺寸上递增,选哪个取决于证书链和握手能承受多少字节。
x509 与 TLS 的接入
crypto/x509 这一侧的变化是能解析、操作 ML-DSA 的私钥、公钥和签名。这意味着用 ML-DSA 签发的证书可以走原有的证书解析路径,不需要为后量子算法单独写一套证书处理逻辑。
crypto/tls 在 TLS 1.3 中支持 ML-DSA,方式是新增三个 SignatureScheme 值:
tls.MLDSA44tls.MLDSA65tls.MLDSA87
接入点是在客户端与服务端的签名方案集合里带上这些值,握手时协商实际使用哪一个。具体字段名以本地 go doc crypto/tls 的输出为准,配置形态大致如下:
cfg := &tls.Config{
MinVersion: tls.VersionTLS13,
SignatureSchemes: []tls.SignatureScheme{
tls.MLDSA65,
tls.MLDSA44,
},
}
MLDSAMu 与 External Mu 签名
Go 1.27 增加了新的 Hash 值 MLDSAMu,用于 External Mu 模式的 ML-DSA 签名。这一模式下,调用方自己计算消息代表(mu)并交给签名/验签逻辑,而不是让签名接口从原始消息内部推算,适合消息已经被分块或流式处理过的场景。
// External Mu:调用方预先算好 mu,用 MLDSAMu 标识所用的哈希
sig, err := mldsa.Sign(priv, mu, crypto.MLDSAMu)
MLKEM1024 与 CurvePreferences
密钥交换一侧,MLKEM1024 现在可以作为选项写进 Config.CurvePreferences:
cfg := &tls.Config{
MinVersion: tls.VersionTLS13,
CurvePreferences: []tls.CurveID{
tls.MLKEM1024,
},
}
CurvePreferences 是有序的,前面的优先。放进 MLKEM1024 后,TLS 1.3 握手会在密钥交换阶段协商使用它。
什么场景现在需要它
后量子迁移不是一次开关切换。签名算法要在证书链、信任锚、协议栈三处同时换掉,而根证书和中间 CA 的更新周期通常以年计。等合规要求或上游 CA 的证书真正变成 ML-DSA 再动手,时间上会很紧。
NIST 已经把 ML-DSA 作为 FIPS 204 标准化,各类合规清单开始把后量子签名纳入要求。现在把 ML-DSA 路径跑通的价值在于:签发链路、验证链路、协议配置都能先验证一遍,等到必须切换时只是把配置打开,而不是从零适配。
还在实验/尚未普及的部分
Go 1.27 提供的是算法与协议支持,不等于生态已经就绪。ML-DSA 证书的签发、CA 的根证书更新、上下游对 ML-DSA 证书链的接受度,这些都还在推进过程中。把这个能力接进生产环境时,需要同时准备好传统算法的回退路径,握手两侧的算法集合要允许协商失败时退回。
握手开销与证书体积
ML-DSA 的公钥和签名尺寸明显大于椭圆曲线方案,这是握手期间要额外传输的字节数。三个参数集里,MLDSA44 最小、MLDSA87 最大,安全强度也同向递增。
取舍点在于:证书链和握手消息变大意味着单次连接传输更多数据,在连接建立频繁的场景下放大成可观的带宽与延迟成本;参数集选得越小,代价越低但安全裕度越薄。实际选择通常按对端能接受的参数集和自身的安全等级要求来定,而不是一律取最大。
Go 1.27 的其他变化
- 泛型方法(generic methods)
uuid包encoding/json/v2,置于encoding/json之后goroutineleakprofile 转为 GA- SIMD 实验
- 按尺寸特化的内存分配:小于 80B 的小对象分配最高便宜 30%,二进制体积增加约 60KB
- Unicode 17