一句话版本
量子计算机能用 Shor 算法在多项式时间内分解大整数、求离散对数,所以 RSA 和椭圆曲线(ECC)会被彻底攻破;对 AES 和哈希,Grover 算法只能把安全性"减半",把密钥加长就能应对。
后量子密码改用量子计算机也不擅长的数学难题,其中的主力是格 :把秘密藏进 b = A s + e ( m o d q ) b = As + e \pmod q b = A s + e ( mod q ) 中那个小小的噪声 e e e 里。
用抽象代数的语言来说,Kyber(ML-KEM)在商环 R q = Z q [ x ] / ( x 256 + 1 ) R_q = \mathbb{Z}_q[x]/(x^{256}+1) R q = Z q [ x ] / ( x 256 + 1 ) 里做运算,而它的快速乘法(NTT)就是中国剩余定理给出的一个环同构。
全文分三层:
通俗理解 :量子计算机到底威胁什么、为什么现在就要换、格密码的直觉
实际用处 :NIST 标准、浏览器 / Signal / iMessage / SSH 的真实部署、迁移时间表、区块链
数学原理 :格与 SVP/CVP、LWE、Ring/Module-LWE、Kyber 全流程、NTT 与 CRT、哈希签名,并附手算例子
第一层:通俗理解
1.1 今天的密码学靠什么撑着
几乎所有"陌生人之间建立安全连接"的场景,都靠公钥密码 :
用途
常用算法
背后的难题
交换密钥(HTTPS 握手)
RSA、ECDH(X25519)
大整数分解、椭圆曲线离散对数
数字签名(证书、软件更新、比特币交易)
RSA、ECDSA、Ed25519
同上
加密大量数据
AES
没有简洁的数学结构,只能暴力搜索
摘要、承诺
SHA-256、SHA-3
同上
公钥算法的安全性建立在一句话上:"这个数学题,经典计算机要算到宇宙毁灭。" 比如把一个 2048 位的数 N = p q N = pq N = pq 分解回 p p p 和 q q q ,已知最好的经典算法(数域筛法)需要的时间大约是
exp ( c ( ln N ) 1 / 3 ( ln ln N ) 2 / 3 ) , \exp\!\Big(c\,(\ln N)^{1/3}(\ln\ln N)^{2/3}\Big), exp ( c ( ln N ) 1/3 ( ln ln N ) 2/3 ) ,
对 RSA-2048 来说完全不可行。
1.2 Shor 算法:RSA 和 ECC 会被彻底攻破
1994 年,Peter Shor 证明:量子计算机可以在多项式时间内分解整数、求离散对数。
直觉是这样的。分解 N N N 可以归结为求一个函数的周期 :随便取 a a a ,看
f ( k ) = a k m o d N f(k) = a^k \bmod N f ( k ) = a k mod N
多久重复一次。设周期是 r r r ,也就是 a r ≡ 1 ( m o d N ) a^r \equiv 1 \pmod N a r ≡ 1 ( mod N ) 。如果 r r r 是偶数,那么
( a r / 2 − 1 ) ( a r / 2 + 1 ) ≡ 0 ( m o d N ) , (a^{r/2}-1)(a^{r/2}+1) \equiv 0 \pmod N, ( a r /2 − 1 ) ( a r /2 + 1 ) ≡ 0 ( mod N ) ,
于是 gcd ( a r / 2 − 1 , N ) \gcd(a^{r/2}-1,\,N) g cd( a r /2 − 1 , N ) 很可能就是 N N N 的一个真因子。
经典计算机找周期只能一个个地试;量子计算机却能让所有 k k k 同时"叠加",再做一次量子傅里叶变换 ,周期就像光栅衍射出的条纹一样显现出来。椭圆曲线离散对数也是一个"隐藏周期"问题,同样会被攻破,而且需要的量子比特比 RSA 还少。
这不是"变慢",而是"归零"
Shor 算法不是把破解时间从 10 30 10^{30} 1 0 30 年缩短到 10 20 10^{20} 1 0 20 年,而是从指数时间降到多项式时间。把 RSA 密钥从 2048 位加长到 4096 位基本没用 ,只能整体换掉。
资源估计还在不断下降:Craig Gidney 在 2025 年的估计是,用不到一百万个带噪声的物理量子比特 、大约一周时间就能分解 RSA-2048。今天最大的量子计算机还差得很远,但这个数字十年前是"十亿级"。
1.3 Grover 算法:AES 只是被削弱
对称密码(AES)和哈希(SHA-256)没有 Shor 能利用的代数结构,量子计算机只能做"无结构搜索"。Grover 算法把在 N N N 个候选里找答案的时间从 N N N 降到大约 N \sqrt{N} N :
2 128 ⟶ 2 128 = 2 64 . 2^{128} \;\longrightarrow\; \sqrt{2^{128}} = 2^{64}. 2 128 ⟶ 2 128 = 2 64 .
所以 AES-128 在量子攻击下"名义上"只剩 64 位安全性。但这只是平方级加速:
把密钥加倍就抵消了 :AES-256 在量子攻击下仍有约 2 128 2^{128} 2 128 的强度。
Grover 必须串行 执行,很难像经典暴力搜索那样分到成千上万台机器上并行,所以实际上连 AES-128 都没那么危险。
算法
经典安全性
量子攻击
量子下的安全性
应对
RSA-2048
约 2 112 2^{112} 2 112
Shor
多项式时间可破
换成后量子算法
ECC P-256 / X25519
约 2 128 2^{128} 2 128
Shor
多项式时间可破
换成后量子算法
AES-128
2 128 2^{128} 2 128
Grover
约 2 64 2^{64} 2 64 (理论)
改用 AES-256
AES-256
2 256 2^{256} 2 256
Grover
约 2 128 2^{128} 2 128
不用动
SHA-256(抗原像)
2 256 2^{256} 2 256
Grover
约 2 128 2^{128} 2 128
不用动
结论:真正需要换掉的是公钥密码,也就是密钥交换和数字签名。
1.4 "先存储,后解密":为什么现在就要换
量子计算机还没造出来,为什么 2024 年就急着换?因为有一种攻击今天就已经在发生 :
Harvest Now, Decrypt Later(先存储,后解密)
攻击者现在就把网络上的加密流量录下来存着 。虽然今天解不开,但等十几年后量子计算机造出来,再用 Shor 算法破解当年的密钥交换,就能读出全部内容。
今天 你用 RSA / ECDH 建立 HTTPS 或聊天连接 攻击者录下全部密文,存进硬盘 若干年后 大规模量子计算机出现 破解 Shor 算法从握手记录里恢复会话密钥 当年的病历、外交电报、商业机密全部曝光 先存储、后解密
衡量是否危险,可以用一个经典的不等式(Mosca 不等式):设
x x x :你的数据需要保密多少年,
y y y :整个系统迁移到后量子算法要多少年,
z z z :距离量子计算机能破解 RSA 还有多少年。
如果
x + y > z , x + y > z, x + y > z ,
那你已经晚了 。病历、国家机密、基因数据的 x x x 动辄几十年,大机构的 y y y 也常常要十年,所以哪怕 z z z 是 15 年也不安全。
注意两类用途的紧迫程度不同:
加密 / 密钥交换 :受"先存储后解密"威胁,最紧迫 ,所以各大公司先换的都是这个。
签名 :签名只需要在验证的那一刻是安全的。量子计算机出现之前签的名,当时验证就是可信的,所以可以晚一点换。但如果像比特币那样,公钥长期暴露在链上,就另当别论(见 2.5)。
1.5 格密码的直觉:在高维格子里找最近点
后量子密码有好几个流派(格、哈希、编码、多变量、同源),其中格密码 是绝对主力。
格 就是空间里排列整齐的点阵。在二维平面上,取两个向量 b 1 , b 2 b_1, b_2 b 1 , b 2 ,它们所有的整数组合
{ a 1 b 1 + a 2 b 2 : a 1 , a 2 ∈ Z } \{\, a_1 b_1 + a_2 b_2 \;:\; a_1, a_2 \in \mathbb{Z} \,\} { a 1 b 1 + a 2 b 2 : a 1 , a 2 ∈ Z }
就构成一个格,看起来像一张倾斜的网格纸。
一个格有很多组不同的"基"能生成它:
好基 :两个向量又短又接近垂直,网格方方正正。
坏基 :两个向量又长又几乎平行,生成的是同一个格,但看起来乱七八糟。
最近向量问题(CVP) :给你空间里任意一个点,找格里离它最近的格点。
拿着好基 :把点的坐标四舍五入到最近的整数组合,基本就对了。
拿着坏基 :四舍五入会跑到很远的地方。
在二维里你可以靠眼睛看,但把维度提到 500 维、1000 维 ,就没有人知道怎么高效地做了。已知最好的算法(无论经典还是量子)都需要指数时间 。
格密码的基本套路
私钥 = 好基(或者一个"小"秘密),公钥 = 坏基(或者混了噪声的数据)。
加密 :选一个格点(编码消息),再加一点小噪声,让它稍微偏离格点。
解密 :有私钥的人能找到最近的格点,去掉噪声;没私钥的人面对的是高维 CVP。
为什么量子计算机帮不上忙? Shor 算法依赖"隐藏周期"这种代数结构,格问题里没有能直接利用的周期。几十年来人们找过量子格算法,最好的也只是常数级的改进。这也是 NIST 选择格作为主力的原因。
第二层:实际用处
2.1 NIST 标准化结果
美国国家标准与技术研究院(NIST)从 2016 年开始公开征集后量子算法,收到 82 份提案,经过三轮多公开分析,于 2024 年 8 月 13 日 发布了前三个正式标准:
标准
名称
原提案
用途
数学基础
FIPS 203
ML-KEM
CRYSTALS-Kyber
密钥封装(替代 ECDH / RSA 加密)
Module-LWE(格)
FIPS 204
ML-DSA
CRYSTALS-Dilithium
数字签名(通用首选)
Module-LWE / Module-SIS(格)
FIPS 205
SLH-DSA
SPHINCS+
数字签名(保守备份)
只依赖哈希函数
FIPS 206(草案)
FN-DSA
Falcon
数字签名(签名更短)
NTRU 格
FIPS 207(计划中)
HQC-KEM
HQC
密钥封装(备份)
纠错码
各个算法的定位:
ML-KEM :通用的密钥交换。几乎所有部署都用它,最常用的参数是 ML-KEM-768。
ML-DSA :通用签名,速度快、实现简单。
SLH-DSA :只要哈希函数不被攻破它就安全,假设最少、最保守。代价是签名很大,而且签名慢。适合根证书、固件签名这类"签得少、要存很久"的场合。
FN-DSA(Falcon) :签名和公钥都比 ML-DSA 小很多,但签名时要在浮点数上做离散高斯采样,很难实现成常数时间、防侧信道,所以标准一直落后。截至 2026 年 10 月仍是草案。
HQC :2025 年 3 月被 NIST 选为 ML-KEM 的备份。它基于纠错码 而不是格,所以万一哪天格被攻破,还有一个数学上完全不同的方案可用。标准计划 2027 年定稿。
参数大小对比(单位:字节):
方案
公钥
密文 / 签名
对比
X25519
32
32
经典 ECDH
ML-KEM-768
1184
1088
约大 35 倍,但计算比 X25519 还快
Ed25519
32
64
经典签名
ML-DSA-65
1952
3309
签名约大 50 倍
FN-DSA-512
897
约 666
比 ML-DSA 小得多
SLH-DSA-128s
32
7856
公钥极小,签名很大
为什么叫"KEM"而不是"加密"?
KEM(Key Encapsulation Mechanism,密钥封装)不加密任意消息,只做一件事:双方安全地得到同一个随机的 32 字节共享密钥,然后用 AES 等对称算法加密真正的数据。这正是 HTTPS 握手需要的。
2.2 为什么要"混合"(hybrid)
几乎所有实际部署都不是直接把 X25519 换成 ML-KEM,而是两个一起用 :
K = K D F ( K X25519 ∥ K ML-KEM ) . K = \mathrm{KDF}\big(K_{\text{X25519}} \,\|\, K_{\text{ML-KEM}}\big). K = KDF ( K X25519 ∥ K ML-KEM ) .
攻击者必须同时 攻破两者才能拿到 K K K :
如果量子计算机来了,X25519 失守,ML-KEM 还撑着。
如果 ML-KEM 被发现有数学漏洞或实现漏洞,X25519 至少保证不比今天差。
这种谨慎是有教训的:2022 年,NIST 第四轮候选 SIKE (同源密码)被一台普通笔记本一个小时内 攻破;签名候选 Rainbow (多变量)也在同年被攻破。新数学难题需要时间检验。
2.3 实际部署
Chrome / Firefox / Safari TLS: X25519MLKEM768
OpenSSH 10 mlkem768x25519-sha256 默认
浏览器与 TLS(HTTPS)
Chrome :2024 年 4 月的 Chrome 124 在桌面端默认启用 X25519+Kyber768 混合密钥交换;2024 年 11 月的 Chrome 131 换成了标准化后的 X25519MLKEM768 。Firefox、Edge 随后跟进,Apple 也在 2025 年的系统更新中给 TLS 加入了混合 ML-KEM。
Cloudflare :从 2022 年起服务端支持后量子握手。2025 年 10 月底,Cloudflare 上过半 的人类流量已经使用后量子密钥交换;据 2026 年 4 月的报道,这一比例已超过 65%。Cloudflare 的目标是 2029 年让认证(签名)也全面后量子化。
Signal
PQXDH (2023 年 9 月):在初始的 X3DH 握手中加入 Kyber-1024,保护会话的建立 。
SPQR / 三重棘轮 (2025 年 10 月 2 日发布):Signal 原本的双棘轮(Double Ratchet)会随着聊天不断更新密钥。SPQR(Sparse Post-Quantum Ratchet)再加一条基于 ML-KEM-768 的棘轮,两边的密钥一起输入 KDF。这样后量子保护覆盖到整个对话过程 ,而不只是开头。
一个和本系列相关的细节:ML-KEM 的数据有一千多字节,Signal 把它切块,并用纠删码 保护,丢掉几块消息也能恢复,原理和 Reed–Solomon 纠错码相同。
Apple iMessage PQ3 (2024 年 2 月,iOS 17.4)
初始握手用 Kyber-1024 和 ECC 混合,之后还会周期性地用 Kyber-768 重新换密钥 。即使某一刻的密钥泄露,之后的消息也能自动恢复安全。Apple 称之为"Level 3"安全等级。
OpenSSH
OpenSSH 9.0(2022 年 4 月)就默认使用 sntrup761x25519-sha512(NTRU Prime + X25519 混合)。
OpenSSH 10.0 (2025 年 4 月)把默认密钥交换改为 mlkem768x25519-sha256 。之后的 10.1 版本还会在连接没有使用后量子密钥交换时发出警告。
但主机密钥和用户密钥(Ed25519、RSA)仍然是经典签名,因为 SSH 的后量子签名标准还在 IETF 讨论中。这再次说明:先换密钥交换,再换签名 。
2.4 迁移时间表
机构
关键节点
NIST IR 8547 (2024 年 11 月草案)
112 位安全的 RSA / ECC:2030 年后弃用 (deprecated),2035 年后禁止 (disallowed)
美国 NSA CNSA 2.0
国家安全系统:软件签名、网络设备等 2025–2030 年间优先 / 只用后量子算法,全面完成目标约 2033–2035 年
欧盟协调路线图 (2025 年)
2026 年底前开始迁移,关键基础设施 2030 年前完成,其余尽可能在 2035 年前完成
英国 NCSC
2028 年完成梳理,2031 年完成优先迁移,2035 年全部完成
总之,2035 年 是各国几乎一致的"RSA/ECC 退役"截止线。
"密码敏捷性"(crypto agility)
这次迁移最大的教训是:很多系统把 RSA 写死在代码、硬件、协议格式里,换一个算法要改好几年。新系统设计时应该让算法可替换 。
2.5 区块链面临的威胁
区块链对量子攻击特别敏感,因为签名就是所有权 ,而且历史数据永远公开。
比特币
用的是 secp256k1 上的 ECDSA / Schnorr 签名,Shor 算法可以从公钥 直接算出私钥 。
地址通常是公钥的哈希 ,哈希只受 Grover 威胁,所以"只收过款、从未花过"的地址相对安全。
危险的是公钥已经暴露 的币:
早期 P2PK 输出直接把公钥写在链上,包括大约一百万枚被认为属于中本聪的币;
重复使用的地址(花过一次,公钥就公开了);
Taproot(P2TR)输出直接包含公钥。
即使地址没暴露,交易广播到上链之间 的几分钟里公钥也是公开的,足够快的量子计算机可以抢先算出私钥、发出冲突交易。
社区在讨论 BIP-360 之类的后量子地址类型提案,但还要面对一个社会问题:那些不迁移的老币怎么办?冻结还是放任被"量子矿工"拿走?
以太坊
外部账户(EOA)同样基于 secp256k1,发过一笔交易后公钥就能从签名里恢复出来。
账户抽象让钱包可以换用任意签名算法,这是以太坊后量子迁移的主要路径之一。
零知识证明层面:基于配对的 SNARK(Groth16、KZG 承诺)依赖椭圆曲线离散对数,会被 Shor 攻破 ;而基于哈希的 STARK (以及里面用到的 FRI 和 Reed–Solomon 码)是后量子安全的。
工作量证明本身 (SHA-256 挖矿)只受 Grover 的平方级加速,而且量子计算机的时钟频率远低于 ASIC 矿机,短期内不是问题。
第三层:数学原理
3.1 格、SVP 与 CVP
定义(格)
设 b 1 , … , b n ∈ R n b_1,\dots,b_n \in \mathbb{R}^n b 1 , … , b n ∈ R n 线性无关,它们生成的格 是
L ( B ) = { ∑ i = 1 n a i b i : a i ∈ Z } = { B a : a ∈ Z n } , \mathcal{L}(B) = \Big\{ \sum_{i=1}^n a_i b_i \;:\; a_i \in \mathbb{Z} \Big\} = \{\, Ba : a \in \mathbb{Z}^n \,\}, L ( B ) = { i = 1 ∑ n a i b i : a i ∈ Z } = { B a : a ∈ Z n } ,
其中 B = [ b 1 ∣ ⋯ ∣ b n ] B = [\,b_1 \mid \cdots \mid b_n\,] B = [ b 1 ∣ ⋯ ∣ b n ] 叫做格的一组基 。
用代数的语言说,格就是 R n \mathbb{R}^n R n 中秩为 n n n 的离散加法子群 ,作为 Z \mathbb{Z} Z -模同构于 Z n \mathbb{Z}^n Z n 。
同一个格有很多组基 :B B B 和 B ′ B' B ′ 生成同一个格,当且仅当存在 U ∈ G L n ( Z ) U \in GL_n(\mathbb{Z}) U ∈ G L n ( Z ) (整数矩阵,行列式为 ± 1 \pm 1 ± 1 )使得 B ′ = B U B' = BU B ′ = B U 。所以 ∣ det B ∣ |\det B| ∣ det B ∣ 不依赖于基的选择,它是格的"基本区域体积"。
两个核心难题:
最短向量问题(SVP) :找格里最短的非零向量,长度记为
λ 1 ( L ) = min v ∈ L ∖ { 0 } ∥ v ∥ . \lambda_1(\mathcal{L}) = \min_{v \in \mathcal{L}\setminus\{0\}} \|v\|. λ 1 ( L ) = v ∈ L ∖ { 0 } min ∥ v ∥.
最近向量问题(CVP) :给定目标点 t ∈ R n t \in \mathbb{R}^n t ∈ R n ,找 v ∈ L v \in \mathcal{L} v ∈ L 使 ∥ t − v ∥ \|t - v\| ∥ t − v ∥ 最小。
已知结果:
LLL 算法 (1982)在多项式时间内找到长度不超过 2 O ( n ) λ 1 2^{O(n)}\lambda_1 2 O ( n ) λ 1 的向量。近似因子是指数级的,对密码学没用。
BKZ 算法 可以在近似因子和运行时间之间取舍,但要得到多项式近似因子,仍然需要 2 Θ ( n ) 2^{\Theta(n)} 2 Θ ( n ) 时间。
精确 SVP 在随机归约下是 NP-困难的。目前没有任何量子算法能在多项式时间内把 SVP 近似到多项式因子。
密码学实际依赖的是近似因子为多项式的 SVP (GapSVP、SIVP)的困难性。
3.2 LWE:带误差的学习
直接用格基构造密码系统(GGH、早期 NTRU 变体)不太方便。2005 年 Oded Regev 提出了一个"代数化"的版本:Learning With Errors(LWE) 。
定义(LWE)
取整数 n n n 、模数 q q q 。随机选一个秘密 向量 s ∈ Z q n s \in \mathbb{Z}_q^n s ∈ Z q n 。给出 m m m 个样本
b = A s + e ( m o d q ) , b = As + e \pmod q, b = A s + e ( mod q ) ,
其中 A ∈ Z q m × n A \in \mathbb{Z}_q^{m\times n} A ∈ Z q m × n 均匀随机,e ∈ Z m e \in \mathbb{Z}^m e ∈ Z m 的每个分量都很小 (比如取自 { − 2 , … , 2 } \{-2,\dots,2\} { − 2 , … , 2 } 或窄的离散高斯分布)。
Search-LWE :已知 ( A , b ) (A, b) ( A , b ) ,求 s s s 。
Decision-LWE :区分 ( A , A s + e ) (A,\, As+e) ( A , A s + e ) 和 ( A , u ) (A,\, u) ( A , u ) ,其中 u u u 均匀随机。
为什么 e e e 是关键? 如果没有 e e e ,b = A s b = As b = A s 就是一个线性方程组,在 Z q \mathbb{Z}_q Z q (q q q 为素数时是域)上用高斯消元,几步就解出 s s s 。加入一点点噪声后:
高斯消元会把误差放大:每做一次行变换,误差就乘上系数、互相累加,很快就淹没了信号。
从格的角度看,{ A x m o d q : x ∈ Z q n } \{\,Ax \bmod q : x\in\mathbb{Z}_q^n\,\} { A x mod q : x ∈ Z q n } 加上 q Z m q\mathbb{Z}^m q Z m 构成一个格,而 b b b 是离某个格点距离很小的一个点。解 LWE 就是解这个格上的 CVP 。
Regev 定理(2005,简述)
若存在高效算法解决(适当参数下的)LWE,则存在量子 算法在最坏情况下 近似求解 n n n 维格上的 GapSVP 和 SIVP。
这个"最坏情况到平均情况"的归约非常强:破解一个随机生成 的 LWE 实例,就等于能解决所有 格上的困难问题。RSA 就没有这样的保证。
从 LWE 到公钥加密(Regev 方案,加密一个比特) :
私钥 :s ∈ Z q n s \in \mathbb{Z}_q^n s ∈ Z q n 。
公钥 :( A , b = A s + e ) (A,\, b = As + e) ( A , b = A s + e ) 。
加密 比特 μ ∈ { 0 , 1 } \mu \in \{0,1\} μ ∈ { 0 , 1 } :随机选 r ∈ { 0 , 1 } m r \in \{0,1\}^m r ∈ { 0 , 1 } m ,计算
u = A T r , v = b T r + μ ⋅ ⌊ q 2 ⌋ . u = A^{\mathsf T} r, \qquad v = b^{\mathsf T} r + \mu \cdot \left\lfloor \tfrac{q}{2} \right\rfloor . u = A T r , v = b T r + μ ⋅ ⌊ 2 q ⌋ .
密文是 ( u , v ) (u, v) ( u , v ) 。
解密 :计算
d = v − u T s = ( A s + e ) T r + μ ⌊ q / 2 ⌋ − r T A s = e T r + μ ⌊ q 2 ⌋ . d = v - u^{\mathsf T} s = (As+e)^{\mathsf T} r + \mu\lfloor q/2\rfloor - r^{\mathsf T} A s = e^{\mathsf T} r + \mu \left\lfloor \tfrac{q}{2} \right\rfloor . d = v − u T s = ( A s + e ) T r + μ ⌊ q /2 ⌋ − r T A s = e T r + μ ⌊ 2 q ⌋ .
因为 e T r e^{\mathsf T} r e T r 很小,d d d 接近 0 0 0 就输出 0 0 0 ,接近 q / 2 q/2 q /2 就输出 1 1 1 。
正确性条件 :∣ e T r ∣ < q / 4 |e^{\mathsf T} r| < q/4 ∣ e T r ∣ < q /4 。
3.3 手算例子:玩具 LWE 加密一个比特
参数
取 n = 2 n = 2 n = 2 ,m = 4 m = 4 m = 4 ,q = 17 q = 17 q = 17 ,所以 ⌊ q / 2 ⌋ = 8 \lfloor q/2 \rfloor = 8 ⌊ q /2 ⌋ = 8 。
私钥:s = ( 2 5 ) s = \begin{pmatrix} 2 \\ 5 \end{pmatrix} s = ( 2 5 )
随机矩阵和误差:
A = ( 3 7 5 1 11 4 2 9 ) , e = ( 1 − 1 0 1 ) . A = \begin{pmatrix} 3 & 7 \\ 5 & 1 \\ 11 & 4 \\ 2 & 9 \end{pmatrix}, \qquad e = \begin{pmatrix} 1 \\ -1 \\ 0 \\ 1 \end{pmatrix}. A = 3 5 11 2 7 1 4 9 , e = 1 − 1 0 1 .
第 1 步:生成公钥。 先算 A s As A s :
A s = ( 3 ⋅ 2 + 7 ⋅ 5 5 ⋅ 2 + 1 ⋅ 5 11 ⋅ 2 + 4 ⋅ 5 2 ⋅ 2 + 9 ⋅ 5 ) = ( 41 15 42 49 ) ≡ ( 7 15 8 15 ) ( m o d 17 ) . As = \begin{pmatrix} 3\cdot 2 + 7\cdot 5 \\ 5\cdot 2 + 1\cdot 5 \\ 11\cdot 2 + 4\cdot 5 \\ 2\cdot 2 + 9\cdot 5 \end{pmatrix}
= \begin{pmatrix} 41 \\ 15 \\ 42 \\ 49 \end{pmatrix}
\equiv \begin{pmatrix} 7 \\ 15 \\ 8 \\ 15 \end{pmatrix} \pmod{17}. A s = 3 ⋅ 2 + 7 ⋅ 5 5 ⋅ 2 + 1 ⋅ 5 11 ⋅ 2 + 4 ⋅ 5 2 ⋅ 2 + 9 ⋅ 5 = 41 15 42 49 ≡ 7 15 8 15 ( mod 17 ) .
再加上误差:
b = A s + e ≡ ( 7 + 1 15 − 1 8 + 0 15 + 1 ) = ( 8 14 8 16 ) ( m o d 17 ) . b = As + e \equiv \begin{pmatrix} 7+1 \\ 15-1 \\ 8+0 \\ 15+1 \end{pmatrix} = \begin{pmatrix} 8 \\ 14 \\ 8 \\ 16 \end{pmatrix} \pmod{17}. b = A s + e ≡ 7 + 1 15 − 1 8 + 0 15 + 1 = 8 14 8 16 ( mod 17 ) .
公开 ( A , b ) (A, b) ( A , b ) ,保密 s s s 。
如果没有误差会怎样?
公钥就是 b ′ = ( 7 , 15 , 8 , 15 ) T b' = (7, 15, 8, 15)^{\mathsf T} b ′ = ( 7 , 15 , 8 , 15 ) T 。攻击者取前两个方程
3 s 1 + 7 s 2 ≡ 7 , 5 s 1 + s 2 ≡ 15 ( m o d 17 ) , 3s_1 + 7s_2 \equiv 7, \qquad 5s_1 + s_2 \equiv 15 \pmod{17}, 3 s 1 + 7 s 2 ≡ 7 , 5 s 1 + s 2 ≡ 15 ( mod 17 ) ,
由第二式得 s 2 ≡ 15 − 5 s 1 s_2 \equiv 15 - 5s_1 s 2 ≡ 15 − 5 s 1 ,代入第一式得 3 s 1 + 105 − 35 s 1 ≡ 7 3s_1 + 105 - 35 s_1 \equiv 7 3 s 1 + 105 − 35 s 1 ≡ 7 ,即 − 32 s 1 ≡ − 98 -32 s_1 \equiv -98 − 32 s 1 ≡ − 98 ,化简为 2 s 1 ≡ 4 ( m o d 17 ) 2s_1 \equiv 4 \pmod{17} 2 s 1 ≡ 4 ( mod 17 ) ,所以 s 1 = 2 s_1 = 2 s 1 = 2 ,s 2 = 5 s_2 = 5 s 2 = 5 。秘密立刻暴露。
有了误差,四个方程互相"不一致",消元得到的结果会被噪声污染。在 n = 2 n=2 n = 2 时还能暴力枚举 17 2 = 289 17^2 = 289 1 7 2 = 289 种可能,但实际的 n n n 是几百,枚举量是 q n q^{n} q n 量级。
第 2 步:加密比特 μ = 1 \mu = 1 μ = 1 。 随机选 r = ( 1 , 0 , 1 , 1 ) T r = (1, 0, 1, 1)^{\mathsf T} r = ( 1 , 0 , 1 , 1 ) T ,也就是取第 1、3、4 个样本相加:
u = A T r = ( 3 + 11 + 2 7 + 4 + 9 ) = ( 16 20 ) ≡ ( 16 3 ) ( m o d 17 ) , u = A^{\mathsf T} r = \begin{pmatrix} 3 + 11 + 2 \\ 7 + 4 + 9 \end{pmatrix} = \begin{pmatrix} 16 \\ 20 \end{pmatrix} \equiv \begin{pmatrix} 16 \\ 3 \end{pmatrix} \pmod{17}, u = A T r = ( 3 + 11 + 2 7 + 4 + 9 ) = ( 16 20 ) ≡ ( 16 3 ) ( mod 17 ) ,
v = b T r + 8 = ( 8 + 8 + 16 ) + 8 = 40 ≡ 6 ( m o d 17 ) . v = b^{\mathsf T} r + 8 = (8 + 8 + 16) + 8 = 40 \equiv 6 \pmod{17}. v = b T r + 8 = ( 8 + 8 + 16 ) + 8 = 40 ≡ 6 ( mod 17 ) .
密文是 ( u , v ) = ( ( 16 , 3 ) T , 6 ) (u, v) = \big((16, 3)^{\mathsf T},\; 6\big) ( u , v ) = ( ( 16 , 3 ) T , 6 ) 。
第 3 步:解密。 用私钥算
u T s = 16 ⋅ 2 + 3 ⋅ 5 = 47 ≡ 13 ( m o d 17 ) , u^{\mathsf T} s = 16\cdot 2 + 3 \cdot 5 = 47 \equiv 13 \pmod{17}, u T s = 16 ⋅ 2 + 3 ⋅ 5 = 47 ≡ 13 ( mod 17 ) ,
d = v − u T s = 6 − 13 = − 7 ≡ 10 ( m o d 17 ) . d = v - u^{\mathsf T} s = 6 - 13 = -7 \equiv 10 \pmod{17}. d = v − u T s = 6 − 13 = − 7 ≡ 10 ( mod 17 ) .
判断规则:Z 17 \mathbb{Z}_{17} Z 17 里离 0 0 0 近的是 { 13 , … , 16 , 0 , 1 , … , 4 } \{13,\dots,16, 0, 1, \dots, 4\} { 13 , … , 16 , 0 , 1 , … , 4 } ,离 8 8 8 近的是 { 5 , … , 12 } \{5, \dots, 12\} { 5 , … , 12 } 。d = 10 d = 10 d = 10 离 8 8 8 只差 2 2 2 ,所以解密为 1 1 1 ✓。
验证一下理论:e T r = 1 + 0 + 1 = 2 e^{\mathsf T} r = 1 + 0 + 1 = 2 e T r = 1 + 0 + 1 = 2 ,确实有
d = e T r + 8 = 2 + 8 = 10. d = e^{\mathsf T} r + 8 = 2 + 8 = 10. d = e T r + 8 = 2 + 8 = 10.
对照:加密 μ = 0 \mu = 0 μ = 0 。 用同一个 r r r ,u u u 不变,v = 32 ≡ 15 v = 32 \equiv 15 v = 32 ≡ 15 ,于是 d = 15 − 13 = 2 d = 15 - 13 = 2 d = 15 − 13 = 2 ,离 0 0 0 近,解密为 0 0 0 ✓。
为什么总是正确? e e e 各分量的绝对值之和是 3 3 3 ,所以对任意 r ∈ { 0 , 1 } 4 r \in \{0,1\}^4 r ∈ { 0 , 1 } 4 都有 ∣ e T r ∣ ≤ 3 < 17 / 4 |e^{\mathsf T} r| \le 3 < 17/4 ∣ e T r ∣ ≤ 3 < 17/4 ,解密永远不会出错。(已用 Python 枚举全部 2 4 2^4 2 4 个 r r r 和两种比特验证。)
真实参数的规模
这个例子里 n = 2 n=2 n = 2 ,攻击者暴力枚举就能破。ML-KEM-768 相当于 n = 768 n = 768 n = 768 、q = 3329 q = 3329 q = 3329 ,暴力枚举需要 3329 768 3329^{768} 332 9 768 次,而最好的格算法(BKZ)也需要约 2 180 2^{180} 2 180 次运算。
3.4 Ring-LWE 与 Module-LWE
普通 LWE 有个大问题:公钥太大 。矩阵 A A A 有 m × n m \times n m × n 个元素,n = 768 n = 768 n = 768 时就是几十万个数,公钥要几百 KB。
Ring-LWE 的想法 :让 A A A 有结构,用一个多项式代替整个矩阵。
取商环
R q = Z q [ x ] / ( x n + 1 ) , R_q = \mathbb{Z}_q[x] / (x^n + 1), R q = Z q [ x ] / ( x n + 1 ) ,
它的元素是次数 < n < n < n 、系数在 Z q \mathbb{Z}_q Z q 中的多项式,乘法做完后用 x n = − 1 x^n = -1 x n = − 1 化简。用抽象代数的语言说,R q R_q R q 就是 Z [ x ] \mathbb{Z}[x] Z [ x ] 模掉理想 ( q , x n + 1 ) (q,\; x^n+1) ( q , x n + 1 ) 得到的商环:
R q ≅ Z [ x ] / ( q , x n + 1 ) . R_q \;\cong\; \mathbb{Z}[x] / (q,\; x^n + 1). R q ≅ Z [ x ] / ( q , x n + 1 ) .
在 R q R_q R q 中,"乘以 a ( x ) a(x) a ( x ) "是 Z q \mathbb{Z}_q Z q -线性映射,对应一个 n × n n\times n n × n 矩阵:
a ( x ) ⋅ s ( x ) ⟷ ( a 0 − a n − 1 ⋯ − a 1 a 1 a 0 ⋯ − a 2 ⋮ ⋮ ⋱ ⋮ a n − 1 a n − 2 ⋯ a 0 ) ( s 0 s 1 ⋮ s n − 1 ) . a(x) \cdot s(x) \quad\longleftrightarrow\quad
\begin{pmatrix}
a_0 & -a_{n-1} & \cdots & -a_1 \\
a_1 & a_0 & \cdots & -a_2 \\
\vdots & \vdots & \ddots & \vdots \\
a_{n-1} & a_{n-2} & \cdots & a_0
\end{pmatrix}
\begin{pmatrix} s_0 \\ s_1 \\ \vdots \\ s_{n-1} \end{pmatrix}. a ( x ) ⋅ s ( x ) ⟷ a 0 a 1 ⋮ a n − 1 − a n − 1 a 0 ⋮ a n − 2 ⋯ ⋯ ⋱ ⋯ − a 1 − a 2 ⋮ a 0 s 0 s 1 ⋮ s n − 1 .
这种矩阵叫反循环矩阵 (negacyclic):每一列都是上一列往下"转一格",转到顶上的元素变号,因为 x ⋅ x n − 1 = x n = − 1 x \cdot x^{n-1} = x^n = -1 x ⋅ x n − 1 = x n = − 1 。整个矩阵只由 n n n 个数决定,存储量从 n 2 n^2 n 2 降到 n n n 。
Ring-LWE
给定 a ∈ R q a \in R_q a ∈ R q 均匀随机,s , e ∈ R q s, e \in R_q s , e ∈ R q 系数都很小,区分 ( a , a s + e ) (a,\; as + e) ( a , a s + e ) 和 ( a , u ) (a,\; u) ( a , u ) 。
为什么用 x n + 1 x^n + 1 x n + 1 ? 取 n = 2 k n = 2^k n = 2 k ,此时
x n + 1 = Φ 2 n ( x ) x^n + 1 = \Phi_{2n}(x) x n + 1 = Φ 2 n ( x )
是第 2 n 2n 2 n 个分圆多项式 (它的复根恰好是全部 2 n 2n 2 n 次本原单位根 e π i ( 2 j + 1 ) / n e^{\pi i (2j+1)/n} e π i ( 2 j + 1 ) / n )。选它有几个原因:
在 Q \mathbb{Q} Q 上不可约 (对 Φ 2 k + 1 \Phi_{2^{k+1}} Φ 2 k + 1 可以对 f ( x + 1 ) f(x+1) f ( x + 1 ) 用 Eisenstein 判别法,p = 2 p=2 p = 2 )。于是 Z [ x ] / ( x n + 1 ) \mathbb{Z}[x]/(x^n+1) Z [ x ] / ( x n + 1 ) 是分圆域 Q ( ζ 2 n ) \mathbb{Q}(\zeta_{2n}) Q ( ζ 2 n ) 的整数环。Lyubashevsky–Peikert–Regev(2010)正是借助这个代数数论结构,把 Ring-LWE 的困难性归约到理想格 上的最坏情况困难问题。
不可约很重要 。反例:如果用 x n − 1 = ( x − 1 ) ( ⋯ ) x^n - 1 = (x-1)(\cdots) x n − 1 = ( x − 1 ) ( ⋯ ) ,就有环同态
Z q [ x ] / ( x n − 1 ) → Z q , f ( x ) ↦ f ( 1 ) . \mathbb{Z}_q[x]/(x^n - 1) \to \mathbb{Z}_q, \qquad f(x) \mapsto f(1). Z q [ x ] / ( x n − 1 ) → Z q , f ( x ) ↦ f ( 1 ) .
把 b = a s + e b = as + e b = a s + e 两边代入 x = 1 x = 1 x = 1 ,得到 b ( 1 ) = a ( 1 ) s ( 1 ) + e ( 1 ) b(1) = a(1)s(1) + e(1) b ( 1 ) = a ( 1 ) s ( 1 ) + e ( 1 ) 。这是只有 1 个未知数 的小问题,e ( 1 ) e(1) e ( 1 ) 又比较小,泄露的信息足以发起攻击。
约化很便宜 :x n ≡ − 1 x^n \equiv -1 x n ≡ − 1 ,模运算只需把高次项变号加回低次项。而且系数不会在约化中膨胀("扩张因子"小),误差保持很小。
适合 NTT :当 q ≡ 1 ( m o d 2 n ) q \equiv 1 \pmod{2n} q ≡ 1 ( mod 2 n ) (或 ( m o d n ) \pmod n ( mod n ) )时,x n + 1 x^n+1 x n + 1 在 Z q \mathbb{Z}_q Z q 上能分解,乘法可以用 NTT 加速(见 3.6)。
Module-LWE:介于两者之间。 Ring-LWE 的结构太"满",Module-LWE 退回一点:用 k × k k \times k k × k 的环元素矩阵
A ∈ R q k × k , s , e ∈ R q k , t = A s + e . \mathbf{A} \in R_q^{k\times k}, \qquad \mathbf{s}, \mathbf{e} \in R_q^{k}, \qquad \mathbf{t} = \mathbf{A}\mathbf{s} + \mathbf{e}. A ∈ R q k × k , s , e ∈ R q k , t = As + e .
这是 R q R_q R q -模 R q k R_q^k R q k 上的 LWE,所以叫 Module-LWE。好处:
环 R q R_q R q 固定为 n = 256 n = 256 n = 256 ,只改 k k k 就能调安全等级 ,同一套 NTT 代码通用。
相比 Ring-LWE,代数结构更少,理论上更不容易被针对结构的攻击利用。
参数集
k k k
等效 LWE 维数 n k nk nk
NIST 安全等级
ML-KEM-512
2
512
1(约等于 AES-128)
ML-KEM-768
3
768
3(约等于 AES-192)
ML-KEM-1024
4
1024
5(约等于 AES-256)
三者都用 n = 256 n = 256 n = 256 、q = 3329 q = 3329 q = 3329 。
3.5 Kyber(ML-KEM)的流程
记号:R q = Z q [ x ] / ( x 256 + 1 ) R_q = \mathbb{Z}_q[x]/(x^{256}+1) R q = Z q [ x ] / ( x 256 + 1 ) ,q = 3329 q = 3329 q = 3329 。"小"多项式的系数从中心二项分布 β η \beta_\eta β η 中采样,取值在 { − η , … , η } \{-\eta, \dots, \eta\} { − η , … , η } ,ML-KEM-768 中 η = 2 \eta = 2 η = 2 。
密钥生成
随机种子 ρ \rho ρ ,用 SHAKE128 把它展开成矩阵 A ∈ R q k × k \mathbf{A} \in R_q^{k\times k} A ∈ R q k × k (这样公钥只需存 32 字节的 ρ \rho ρ ,不用存整个矩阵)。
采样小的 s , e ∈ R q k \mathbf{s}, \mathbf{e} \in R_q^k s , e ∈ R q k 。
计算 t = A s + e \mathbf{t} = \mathbf{A}\mathbf{s} + \mathbf{e} t = As + e 。
公钥 p k = ( ρ , t ) \mathrm{pk} = (\rho, \mathbf{t}) pk = ( ρ , t ) ,私钥 s k = s \mathrm{sk} = \mathbf{s} sk = s 。
加密(消息 m m m 是 256 比特,看成系数为 0 / 1 0/1 0/1 的多项式)
采样小的 r , e 1 ∈ R q k \mathbf{r}, \mathbf{e}_1 \in R_q^k r , e 1 ∈ R q k 和小的 e 2 ∈ R q e_2 \in R_q e 2 ∈ R q 。
计算
u = A T r + e 1 , v = t T r + e 2 + ⌈ q 2 ⌋ ⋅ m . \mathbf{u} = \mathbf{A}^{\mathsf T}\mathbf{r} + \mathbf{e}_1, \qquad
v = \mathbf{t}^{\mathsf T}\mathbf{r} + e_2 + \left\lceil \tfrac{q}{2} \right\rfloor \cdot m. u = A T r + e 1 , v = t T r + e 2 + ⌈ 2 q ⌋ ⋅ m .
把 u , v \mathbf{u}, v u , v 的系数压缩 (只保留高位比特),输出密文 c = ( u , v ) c = (\mathbf{u}, v) c = ( u , v ) 。
解密
v − s T u = e T r + e 2 − s T e 1 ⏟ 小噪声 + ⌈ q 2 ⌋ ⋅ m . v - \mathbf{s}^{\mathsf T}\mathbf{u}
= \underbrace{\mathbf{e}^{\mathsf T}\mathbf{r} + e_2 - \mathbf{s}^{\mathsf T}\mathbf{e}_1}_{\text{小噪声}} \;+\; \left\lceil \tfrac{q}{2} \right\rfloor \cdot m . v − s T u = 小噪声 e T r + e 2 − s T e 1 + ⌈ 2 q ⌋ ⋅ m .
对每个系数四舍五入:接近 0 0 0 记为 0 0 0 ,接近 q / 2 ≈ 1665 q/2 \approx 1665 q /2 ≈ 1665 记为 1 1 1 ,就得到 m m m 。
推导只用了 t = A s + e \mathbf{t} = \mathbf{A}\mathbf{s}+\mathbf{e} t = As + e 和 R q R_q R q 的交换性:
t T r − s T A T r = ( A s ) T r + e T r − s T A T r = e T r . \mathbf{t}^{\mathsf T}\mathbf{r} - \mathbf{s}^{\mathsf T}\mathbf{A}^{\mathsf T}\mathbf{r}
= (\mathbf{A}\mathbf{s})^{\mathsf T}\mathbf{r} + \mathbf{e}^{\mathsf T}\mathbf{r} - \mathbf{s}^{\mathsf T}\mathbf{A}^{\mathsf T}\mathbf{r}
= \mathbf{e}^{\mathsf T}\mathbf{r}. t T r − s T A T r = ( As ) T r + e T r − s T A T r = e T r .
这和 3.3 的玩具例子结构完全相同 ,只是把"整数"换成了"R q R_q R q 里的多项式",一次加密 256 个比特而不是 1 个。
Bob Alice Bob Alice 采样小的 s, e t = A s + e 随机选 32 字节 m u = A^T r + e1 v = t^T r + e2 + round(q/2) m v - s^T u 四舍五入 得到 m 双方用哈希从 m 派生共享密钥 K 公钥 (rho, t) 密文 (u, v)
从"加密"到"KEM":Fujisaki–Okamoto 变换
上面的方案只能抵抗被动攻击(IND-CPA)。ML-KEM 在外面套了一层 FO 变换 :加密用的随机数 r , e 1 , e 2 \mathbf{r}, \mathbf{e}_1, e_2 r , e 1 , e 2 都由 m m m 和公钥的哈希确定性地生成;解密方解出 m m m 后重新加密一遍 ,检查是否得到同一个密文,不一致就输出一个伪随机密钥("隐式拒绝")。这样就能抵抗选择密文攻击(IND-CCA2)。
3.6 NTT:用中国剩余定理加速乘法
Kyber 的主要计算量是 R q R_q R q 中的多项式乘法。直接相乘需要 256 2 = 65536 256^2 = 65536 25 6 2 = 65536 次系数乘法,NTT(数论变换) 可以把它降到 O ( n log n ) O(n\log n) O ( n log n ) 量级。NTT 就是有限域上的 FFT,背后的数学是抽象代数里的中国剩余定理 。
中国剩余定理(多项式环版本)
设 F F F 是域,f = f 1 f 2 ⋯ f r f = f_1 f_2 \cdots f_r f = f 1 f 2 ⋯ f r ,且 f i f_i f i 两两互素。则有环同构
F [ x ] / ( f ) → ∼ F [ x ] / ( f 1 ) × ⋯ × F [ x ] / ( f r ) , g ↦ ( g m o d f 1 , … , g m o d f r ) . F[x]/(f) \;\xrightarrow{\;\sim\;}\; F[x]/(f_1) \times \cdots \times F[x]/(f_r), \qquad g \mapsto (g \bmod f_1,\; \dots,\; g \bmod f_r). F [ x ] / ( f ) ∼ F [ x ] / ( f 1 ) × ⋯ × F [ x ] / ( f r ) , g ↦ ( g mod f 1 , … , g mod f r ) .
互素保证了理想 ( f i ) (f_i) ( f i ) 两两互素(( f i ) + ( f j ) = F [ x ] (f_i) + (f_j) = F[x] ( f i ) + ( f j ) = F [ x ] ),这正是 CRT 的条件。
关键点 :同构右边的乘法是逐分量 的。所以计算 g ⋅ h g \cdot h g ⋅ h 时,可以:
把 g , h g, h g , h 分别映到右边(正向 NTT);
逐分量相乘(便宜);
映回左边(逆向 NTT)。
而第 1、3 步可以像 FFT 那样递归地对半拆分 x 2 m − c 2 = ( x m − c ) ( x m + c ) x^{2m} - c^2 = (x^m - c)(x^m + c) x 2 m − c 2 = ( x m − c ) ( x m + c ) ,总共 log n \log n log n 层。
先看一个小例子 :Z 17 [ x ] / ( x 4 + 1 ) \mathbb{Z}_{17}[x]/(x^4+1) Z 17 [ x ] / ( x 4 + 1 ) 。
因为 17 ≡ 1 ( m o d 8 ) 17 \equiv 1 \pmod 8 17 ≡ 1 ( mod 8 ) ,Z 17 × \mathbb{Z}_{17}^\times Z 17 × (循环群,阶为 16 16 16 )中有 8 次本原单位根,所以 x 4 + 1 x^4 + 1 x 4 + 1 在 Z 17 \mathbb{Z}_{17} Z 17 上完全分解。它的四个根是 2 , 8 , 9 , 15 2, 8, 9, 15 2 , 8 , 9 , 15 (例如 2 4 = 16 ≡ − 1 2^4 = 16 \equiv -1 2 4 = 16 ≡ − 1 )。于是
Z 17 [ x ] / ( x 4 + 1 ) ≅ Z 17 [ x ] / ( x − 2 ) × Z 17 [ x ] / ( x − 8 ) × Z 17 [ x ] / ( x − 9 ) × Z 17 [ x ] / ( x − 15 ) ≅ Z 17 4 , \mathbb{Z}_{17}[x]/(x^4+1) \;\cong\; \mathbb{Z}_{17}[x]/(x-2) \times \mathbb{Z}_{17}[x]/(x-8) \times \mathbb{Z}_{17}[x]/(x-9) \times \mathbb{Z}_{17}[x]/(x-15) \;\cong\; \mathbb{Z}_{17}^4, Z 17 [ x ] / ( x 4 + 1 ) ≅ Z 17 [ x ] / ( x − 2 ) × Z 17 [ x ] / ( x − 8 ) × Z 17 [ x ] / ( x − 9 ) × Z 17 [ x ] / ( x − 15 ) ≅ Z 17 4 ,
同构映射就是代值 g ↦ ( g ( 2 ) , g ( 8 ) , g ( 9 ) , g ( 15 ) ) g \mapsto \big(g(2), g(8), g(9), g(15)\big) g ↦ ( g ( 2 ) , g ( 8 ) , g ( 9 ) , g ( 15 ) ) 。
取 f = 1 + 2 x + x 3 f = 1 + 2x + x^3 f = 1 + 2 x + x 3 ,g = 3 + x 2 g = 3 + x^2 g = 3 + x 2 。直接计算(用 x 4 = − 1 x^4 = -1 x 4 = − 1 ,x 5 = − x x^5 = -x x 5 = − x ):
f g = 3 + 6 x + x 2 + 5 x 3 + x 5 = 3 + 5 x + x 2 + 5 x 3 . fg = 3 + 6x + x^2 + 5x^3 + x^5 = 3 + 5x + x^2 + 5x^3. f g = 3 + 6 x + x 2 + 5 x 3 + x 5 = 3 + 5 x + x 2 + 5 x 3 .
用代值验证:
点 a a a
f ( a ) f(a) f ( a )
g ( a ) g(a) g ( a )
f ( a ) g ( a ) m o d 17 f(a)g(a) \bmod 17 f ( a ) g ( a ) mod 17
( f g ) ( a ) (fg)(a) ( f g ) ( a )
2 2 2
13 13 13
7 7 7
6 6 6
6 6 6
8 8 8
2 2 2
16 16 16
15 15 15
15 15 15
9 9 9
0 0 0
16 16 16
0 0 0
0 0 0
15 15 15
6 6 6
7 7 7
8 8 8
8 8 8
完全吻合。顺便注意 f ( 9 ) = 0 f(9) = 0 f ( 9 ) = 0 :f f f 不是零多项式,却在一个分量上为零,所以 f f f 是这个环里的零因子 。这说明 R q R_q R q 不是整环,和"x 4 + 1 x^4+1 x 4 + 1 在 Z 17 \mathbb{Z}_{17} Z 17 上可约"是一回事。
回到 Kyber :q = 3329 q = 3329 q = 3329 ,q − 1 = 3328 = 2 8 ⋅ 13 q - 1 = 3328 = 2^8 \cdot 13 q − 1 = 3328 = 2 8 ⋅ 13 。
Z 3329 × \mathbb{Z}_{3329}^\times Z 3329 × 是 3328 3328 3328 阶循环群,含有 256 256 256 次本原单位根,Kyber 取 ζ = 17 \zeta = 17 ζ = 17 (可以验证 17 17 17 的阶恰好是 256 256 256 ,且 17 128 ≡ − 1 17^{128} \equiv -1 1 7 128 ≡ − 1 )。
但 512 ∤ 3328 512 \nmid 3328 512 ∤ 3328 ,没有 512 次本原单位根 ,所以 x 256 + 1 x^{256}+1 x 256 + 1 不能完全分解成一次因子,只能分解成 128 个二次因子:
x 256 + 1 = ∏ i = 0 127 ( x 2 − ζ i ) , ζ i = ζ 2 b r 7 ( i ) + 1 , x^{256} + 1 = \prod_{i=0}^{127} \big(x^2 - \zeta_i\big), \qquad \zeta_i = \zeta^{\,2\,\mathrm{br}_7(i)+1}, x 256 + 1 = i = 0 ∏ 127 ( x 2 − ζ i ) , ζ i = ζ 2 br 7 ( i ) + 1 ,
其中 b r 7 ( i ) \mathrm{br}_7(i) br 7 ( i ) 表示把 i i i 的 7 位二进制表示反转(这只是为了 FFT 递归时的顺序)。这 128 个 ζ i \zeta_i ζ i 恰好是 y 128 = − 1 y^{128} = -1 y 128 = − 1 的全部根。由 CRT:
R q = Z q [ x ] / ( x 256 + 1 ) ≅ ∏ i = 0 127 Z q [ x ] / ( x 2 − ζ i ) . R_q = \mathbb{Z}_q[x]/(x^{256}+1) \;\cong\; \prod_{i=0}^{127} \mathbb{Z}_q[x]/(x^2 - \zeta_i). R q = Z q [ x ] / ( x 256 + 1 ) ≅ i = 0 ∏ 127 Z q [ x ] / ( x 2 − ζ i ) .
再进一步:x 2 − ζ i x^2 - \zeta_i x 2 − ζ i 在 Z q \mathbb{Z}_q Z q 上不可约 。如果 ζ i = y 2 \zeta_i = y^2 ζ i = y 2 ,那么 y y y 的阶就是 512 512 512 ,而这样的元素不存在。所以每个因子都是一个域 F q 2 \mathbb{F}_{q^2} F q 2 ,于是
R q ≅ F q 2 × ⋯ × F q 2 ⏟ 128 个 . R_q \;\cong\; \underbrace{\mathbb{F}_{q^2} \times \cdots \times \mathbb{F}_{q^2}}_{128\text{ 个}}. R q ≅ 128 个 F q 2 × ⋯ × F q 2 .
在 NTT 域里,两个多项式相乘就变成 128 次"模 x 2 − ζ i x^2 - \zeta_i x 2 − ζ i 的一次多项式乘法":
( a 0 + a 1 x ) ( b 0 + b 1 x ) ≡ ( a 0 b 0 + ζ i a 1 b 1 ) + ( a 0 b 1 + a 1 b 0 ) x ( m o d x 2 − ζ i ) . (a_0 + a_1 x)(b_0 + b_1 x) \equiv (a_0 b_0 + \zeta_i\, a_1 b_1) + (a_0 b_1 + a_1 b_0)\, x \pmod{x^2 - \zeta_i}. ( a 0 + a 1 x ) ( b 0 + b 1 x ) ≡ ( a 0 b 0 + ζ i a 1 b 1 ) + ( a 0 b 1 + a 1 b 0 ) x ( mod x 2 − ζ i ) .
工程上的妙处
Kyber 规定 A \mathbf{A} A 直接在 NTT 域中采样 ,公钥 t \mathbf{t} t 也以 NTT 形式存储,省掉大量正逆变换。
ML-DSA 用 q = 8380417 q = 8380417 q = 8380417 ,它满足 q ≡ 1 ( m o d 512 ) q \equiv 1 \pmod{512} q ≡ 1 ( mod 512 ) ,所以 x 256 + 1 x^{256}+1 x 256 + 1 能完全分解成 256 个一次因子,NTT 一路拆到底。
这也解释了为什么 ML-KEM 比 X25519 还快:NTT 和小模数下的整数运算在 CPU 上非常高效。
3.7 ML-DSA 的签名思路(简述)
ML-DSA(Dilithium)采用"带中止的 Fiat–Shamir ":
承诺 :随机选小的 y \mathbf{y} y ,计算 w = A y \mathbf{w} = \mathbf{A}\mathbf{y} w = Ay 的高位比特 w 1 \mathbf{w}_1 w 1 。
挑战 :c = H ( 消息 ∥ w 1 ) c = H(\text{消息} \,\|\, \mathbf{w}_1) c = H ( 消息 ∥ w 1 ) ,c c c 是只有少数系数为 ± 1 \pm 1 ± 1 的稀疏多项式。
响应 :z = y + c s 1 \mathbf{z} = \mathbf{y} + c\,\mathbf{s}_1 z = y + c s 1 。
中止检查 :如果 z \mathbf{z} z 的系数太大(可能泄露 s 1 \mathbf{s}_1 s 1 的信息),就丢掉重来 。通过拒绝采样,z \mathbf{z} z 的分布与私钥无关。
验证者检查 A z − c t \mathbf{A}\mathbf{z} - c\,\mathbf{t} Az − c t 的高位是否等于 w 1 \mathbf{w}_1 w 1 ,以及 z \mathbf{z} z 是否足够小。其安全性依赖 Module-LWE 和 Module-SIS(找短向量 x \mathbf{x} x 使 A x = 0 \mathbf{A}\mathbf{x} = 0 Ax = 0 )。
3.8 基于哈希的签名:从 Lamport 到 SPHINCS+
哈希签名的安全性只依赖哈希函数 的单向性和抗碰撞性,没有任何代数结构。这是最保守的方案。
Lamport 一次性签名(1979) :设 H H H 输出 256 比特。
私钥 :512 512 512 个随机字符串 x i , 0 , x i , 1 x_{i,0}, x_{i,1} x i , 0 , x i , 1 ,i = 1 , … , 256 i = 1, \dots, 256 i = 1 , … , 256 。
公钥 :它们的哈希 y i , b = H ( x i , b ) y_{i,b} = H(x_{i,b}) y i , b = H ( x i , b ) 。
签名 消息 M M M :设 h = H ( M ) = h 1 h 2 ⋯ h 256 h = H(M) = h_1 h_2 \cdots h_{256} h = H ( M ) = h 1 h 2 ⋯ h 256 ,对每一位公开 x i , h i x_{i,h_i} x i , h i 。
验证 :检查 H ( 签名 i ) = y i , h i H(\text{签名}_i) = y_{i,h_i} H ( 签名 i ) = y i , h i 对所有 i i i 成立。
伪造签名需要对某个 y i , b y_{i,b} y i , b 求哈希原像。但每个密钥只能用一次 :签两条消息就会暴露两边的部分私钥,攻击者可以拼出新签名。
改进路线 :
Merkle 树 (XMSS / LMS) 2^h 个一次性密钥 需要记录状态
SPHINCS+ / SLH-DSA 超树 + FORS 无状态
Winternitz(WOTS) :每次处理 w w w 个比特,用哈希链 x → H ( x ) → H ( H ( x ) ) → ⋯ x \to H(x) \to H(H(x)) \to \cdots x → H ( x ) → H ( H ( x )) → ⋯ 表示 0 0 0 到 2 w − 1 2^w - 1 2 w − 1 ,签名大幅变短。
Merkle 树 :把 2 h 2^h 2 h 个一次性公钥作为叶子,建一棵哈希树,根 就是总公钥。签名 = 一次性签名 + 从叶子到根的认证路径(h h h 个哈希值)。缺点是签名者必须记住 用过哪些叶子(有状态),XMSS、LMS(NIST SP 800-208)就是这一类。状态一旦出错(比如虚拟机快照回滚),就可能复用叶子,导致私钥泄露。
SPHINCS+(SLH-DSA) :
用超树 (多层 Merkle 树叠起来)提供海量叶子,例如 2 63 2^{63} 2 63 个以上;
用消息的哈希伪随机地选一个叶子 ,叶子多到几乎不可能撞上;
叶子上用 FORS (少次签名)而不是一次性签名,即使偶尔撞上同一个叶子也还安全。
于是不需要记录状态 。代价是签名有 7.8 KB 到约 50 KB,签名速度也比 ML-DSA 慢得多。
总结
Module-LWE R_q = Z_q[x]/(x^256+1)
层次
要点
通俗理解
Shor 让 RSA/ECC 归零,Grover 只让 AES 减半;"先存储后解密"使迁移刻不容缓;格密码 = 高维空间里找最近点
实际用处
2024 年 FIPS 203/204/205;Chrome、Cloudflare、Signal、iMessage、OpenSSH 已默认使用混合 ML-KEM;2035 年是 RSA/ECC 的退役线
数学原理
LWE:b = A s + e b = As + e b = A s + e ,噪声 e e e 让线性代数失效;R q = Z q [ x ] / ( x 256 + 1 ) R_q = \mathbb{Z}_q[x]/(x^{256}+1) R q = Z q [ x ] / ( x 256 + 1 ) 压缩公钥;NTT 就是 CRT 同构 R q ≅ ∏ Z q [ x ] / ( x 2 − ζ i ) R_q \cong \prod \mathbb{Z}_q[x]/(x^2 - \zeta_i) R q ≅ ∏ Z q [ x ] / ( x 2 − ζ i )
和抽象代数的联系
商环 :R q = Z [ x ] / ( q , x 256 + 1 ) R_q = \mathbb{Z}[x]/(q, x^{256}+1) R q = Z [ x ] / ( q , x 256 + 1 )
不可约多项式 :x n + 1 x^n+1 x n + 1 在 Q \mathbb{Q} Q 上不可约,在 Z q \mathbb{Z}_q Z q 上可约;后者正是 NTT 能用的原因
环同态 :代值映射 f ↦ f ( 1 ) f \mapsto f(1) f ↦ f ( 1 ) 解释了为什么不能用 x n − 1 x^n - 1 x n − 1
中国剩余定理 :NTT 的全部数学内容
零因子 :R q R_q R q 不是整环,例子中 f ( 9 ) = 0 f(9) = 0 f ( 9 ) = 0
有限域 :每个 CRT 分量 Z q [ x ] / ( x 2 − ζ i ) ≅ F q 2 \mathbb{Z}_q[x]/(x^2 - \zeta_i) \cong \mathbb{F}_{q^2} Z q [ x ] / ( x 2 − ζ i ) ≅ F q 2