Caloogy 文章
English

后量子密码科普

日期
2026 年 10 月 19 日
系列
密码学
阅读
18 分钟
主题
Post quantumLatticeLWEKyber

一句话版本

量子计算机能用 Shor 算法在多项式时间内分解大整数、求离散对数,所以 RSA 和椭圆曲线(ECC)会被彻底攻破;对 AES 和哈希,Grover 算法只能把安全性"减半",把密钥加长就能应对。 后量子密码改用量子计算机也不擅长的数学难题,其中的主力是格:把秘密藏进 b=As+e(modq)b = As + e \pmod q 中那个小小的噪声 ee 里。 用抽象代数的语言来说,Kyber(ML-KEM)在商环 Rq=Zq[x]/(x256+1)R_q = \mathbb{Z}_q[x]/(x^{256}+1) 里做运算,而它的快速乘法(NTT)就是中国剩余定理给出的一个环同构。

全文分三层:

  1. 通俗理解:量子计算机到底威胁什么、为什么现在就要换、格密码的直觉
  2. 实际用处:NIST 标准、浏览器 / Signal / iMessage / SSH 的真实部署、迁移时间表、区块链
  3. 数学原理:格与 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=pqN = pq 分解回 pp 和 qq,已知最好的经典算法(数域筛法)需要的时间大约是

exp⁡ ⁣(c (ln⁡N)1/3(ln⁡ln⁡N)2/3),\exp\!\Big(c\,(\ln N)^{1/3}(\ln\ln N)^{2/3}\Big),

对 RSA-2048 来说完全不可行。

1.2 Shor 算法:RSA 和 ECC 会被彻底攻破

1994 年,Peter Shor 证明:量子计算机可以在多项式时间内分解整数、求离散对数。

直觉是这样的。分解 NN 可以归结为求一个函数的周期:随便取 aa,看

f(k)=ak mod Nf(k) = a^k \bmod N

多久重复一次。设周期是 rr,也就是 ar≡1(modN)a^r \equiv 1 \pmod N。如果 rr 是偶数,那么

(ar/2−1)(ar/2+1)≡0(modN),(a^{r/2}-1)(a^{r/2}+1) \equiv 0 \pmod N,

于是 gcd⁡(ar/2−1, N)\gcd(a^{r/2}-1,\,N) 很可能就是 NN 的一个真因子。

经典计算机找周期只能一个个地试;量子计算机却能让所有 kk 同时"叠加",再做一次量子傅里叶变换,周期就像光栅衍射出的条纹一样显现出来。椭圆曲线离散对数也是一个"隐藏周期"问题,同样会被攻破,而且需要的量子比特比 RSA 还少。

这不是"变慢",而是"归零"

Shor 算法不是把破解时间从 103010^{30} 年缩短到 102010^{20} 年,而是从指数时间降到多项式时间。把 RSA 密钥从 2048 位加长到 4096 位基本没用,只能整体换掉。 资源估计还在不断下降:Craig Gidney 在 2025 年的估计是,用不到一百万个带噪声的物理量子比特、大约一周时间就能分解 RSA-2048。今天最大的量子计算机还差得很远,但这个数字十年前是"十亿级"。

1.3 Grover 算法:AES 只是被削弱

对称密码(AES)和哈希(SHA-256)没有 Shor 能利用的代数结构,量子计算机只能做"无结构搜索"。Grover 算法把在 NN 个候选里找答案的时间从 NN 降到大约 N\sqrt{N}:

2128  ⟶  2128=264.2^{128} \;\longrightarrow\; \sqrt{2^{128}} = 2^{64}.

所以 AES-128 在量子攻击下"名义上"只剩 64 位安全性。但这只是平方级加速:

算法 经典安全性 量子攻击 量子下的安全性 应对
RSA-2048 约 21122^{112} Shor 多项式时间可破 换成后量子算法
ECC P-256 / X25519 约 21282^{128} Shor 多项式时间可破 换成后量子算法
AES-128 21282^{128} Grover 约 2642^{64}(理论) 改用 AES-256
AES-256 22562^{256} Grover 约 21282^{128} 不用动
SHA-256(抗原像) 22562^{256} Grover 约 21282^{128} 不用动

结论:真正需要换掉的是公钥密码,也就是密钥交换和数字签名。

1.4 "先存储,后解密":为什么现在就要换

量子计算机还没造出来,为什么 2024 年就急着换?因为有一种攻击今天就已经在发生:

Harvest Now, Decrypt Later(先存储,后解密)

攻击者现在就把网络上的加密流量录下来存着。虽然今天解不开,但等十几年后量子计算机造出来,再用 Shor 算法破解当年的密钥交换,就能读出全部内容。

今天你用 RSA / ECDH 建立HTTPS 或聊天连接攻击者录下全部密文,存进硬盘若干年后大规模量子计算机出现破解Shor算法从握手记录里恢复会话密钥当年的病历、外交电报、商业机密全部曝光先存储、后解密

衡量是否危险,可以用一个经典的不等式(Mosca 不等式):设

如果

x+y>z,x + y > z,

那你已经晚了。病历、国家机密、基因数据的 xx 动辄几十年,大机构的 yy 也常常要十年,所以哪怕 zz 是 15 年也不安全。

注意两类用途的紧迫程度不同:

1.5 格密码的直觉:在高维格子里找最近点

后量子密码有好几个流派(格、哈希、编码、多变量、同源),其中格密码是绝对主力。

格就是空间里排列整齐的点阵。在二维平面上,取两个向量 b1,b2b_1, b_2,它们所有的整数组合

{ a1b1+a2b2  :  a1,a2∈Z }\{\, a_1 b_1 + a_2 b_2 \;:\; a_1, a_2 \in \mathbb{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 密钥封装(备份) 纠错码

各个算法的定位:

参数大小对比(单位:字节):

方案 公钥 密文 / 签名 对比
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=KDF(KX25519 ∥ KML-KEM).K = \mathrm{KDF}\big(K_{\text{X25519}} \,\|\, K_{\text{ML-KEM}}\big).

攻击者必须同时攻破两者才能拿到 KK:

这种谨慎是有教训的:2022 年,NIST 第四轮候选 SIKE(同源密码)被一台普通笔记本一个小时内攻破;签名候选 Rainbow(多变量)也在同年被攻破。新数学难题需要时间检验。

2.3 实际部署

仍在进行

证书 / PKI 的后量子签名

区块链地址与签名

已大规模部署

Chrome / Firefox / Safari
TLS: X25519MLKEM768

Cloudflare
超过一半的人类流量

Signal
PQXDH + SPQR

iMessage
PQ3

OpenSSH 10
mlkem768x25519-sha256 默认

浏览器与 TLS(HTTPS)

Signal

Apple iMessage PQ3(2024 年 2 月,iOS 17.4)

OpenSSH

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 区块链面临的威胁

区块链对量子攻击特别敏感,因为签名就是所有权,而且历史数据永远公开。

比特币

以太坊

工作量证明本身(SHA-256 挖矿)只受 Grover 的平方级加速,而且量子计算机的时钟频率远低于 ASIC 矿机,短期内不是问题。


第三层:数学原理

3.1 格、SVP 与 CVP

定义(格)

设 b1,…,bn∈Rnb_1,\dots,b_n \in \mathbb{R}^n 线性无关,它们生成的格是 L(B)={∑i=1naibi  :  ai∈Z}={ Ba:a∈Zn },\mathcal{L}(B) = \Big\{ \sum_{i=1}^n a_i b_i \;:\; a_i \in \mathbb{Z} \Big\} = \{\, Ba : a \in \mathbb{Z}^n \,\}, 其中 B=[ b1∣⋯∣bn ]B = [\,b_1 \mid \cdots \mid b_n\,] 叫做格的一组基。

用代数的语言说,格就是 Rn\mathbb{R}^n 中秩为 nn 的离散加法子群,作为 Z\mathbb{Z}-模同构于 Zn\mathbb{Z}^n。

同一个格有很多组基:BB 和 B′B' 生成同一个格,当且仅当存在 U∈GLn(Z)U \in GL_n(\mathbb{Z})(整数矩阵,行列式为 ±1\pm 1)使得 B′=BUB' = BU。所以 ∣det⁡B∣|\det B| 不依赖于基的选择,它是格的"基本区域体积"。

两个核心难题:

已知结果:

密码学实际依赖的是近似因子为多项式的 SVP(GapSVP、SIVP)的困难性。

3.2 LWE:带误差的学习

直接用格基构造密码系统(GGH、早期 NTRU 变体)不太方便。2005 年 Oded Regev 提出了一个"代数化"的版本:Learning With Errors(LWE)。

定义(LWE)

取整数 nn、模数 qq。随机选一个秘密向量 s∈Zqns \in \mathbb{Z}_q^n。给出 mm 个样本 b=As+e(modq),b = As + e \pmod q, 其中 A∈Zqm×nA \in \mathbb{Z}_q^{m\times n} 均匀随机,e∈Zme \in \mathbb{Z}^m 的每个分量都很小(比如取自 {−2,…,2}\{-2,\dots,2\} 或窄的离散高斯分布)。

  • Search-LWE:已知 (A,b)(A, b),求 ss。
  • Decision-LWE:区分 (A, As+e)(A,\, As+e) 和 (A, u)(A,\, u),其中 uu 均匀随机。

为什么 ee 是关键? 如果没有 ee,b=Asb = As 就是一个线性方程组,在 Zq\mathbb{Z}_q(qq 为素数时是域)上用高斯消元,几步就解出 ss。加入一点点噪声后:

Regev 定理(2005,简述)

若存在高效算法解决(适当参数下的)LWE,则存在量子算法在最坏情况下近似求解 nn 维格上的 GapSVP 和 SIVP。

这个"最坏情况到平均情况"的归约非常强:破解一个随机生成的 LWE 实例,就等于能解决所有格上的困难问题。RSA 就没有这样的保证。

从 LWE 到公钥加密(Regev 方案,加密一个比特):

3.3 手算例子:玩具 LWE 加密一个比特

参数

取 n=2n = 2,m=4m = 4,q=17q = 17,所以 ⌊q/2⌋=8\lfloor q/2 \rfloor = 8。

  • 私钥:s=(25)s = \begin{pmatrix} 2 \\ 5 \end{pmatrix}
  • 随机矩阵和误差: A=(375111429),e=(1−101).A = \begin{pmatrix} 3 & 7 \\ 5 & 1 \\ 11 & 4 \\ 2 & 9 \end{pmatrix}, \qquad e = \begin{pmatrix} 1 \\ -1 \\ 0 \\ 1 \end{pmatrix}.

第 1 步:生成公钥。 先算 AsAs:

As=(3⋅2+7⋅55⋅2+1⋅511⋅2+4⋅52⋅2+9⋅5)=(41154249)≡(715815)(mod17).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}.

再加上误差:

b=As+e≡(7+115−18+015+1)=(814816)(mod17).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}.

公开 (A,b)(A, b),保密 ss。

如果没有误差会怎样?

公钥就是 b′=(7,15,8,15)Tb' = (7, 15, 8, 15)^{\mathsf T}。攻击者取前两个方程 3s1+7s2≡7,5s1+s2≡15(mod17),3s_1 + 7s_2 \equiv 7, \qquad 5s_1 + s_2 \equiv 15 \pmod{17}, 由第二式得 s2≡15−5s1s_2 \equiv 15 - 5s_1,代入第一式得 3s1+105−35s1≡73s_1 + 105 - 35 s_1 \equiv 7,即 −32s1≡−98-32 s_1 \equiv -98,化简为 2s1≡4(mod17)2s_1 \equiv 4 \pmod{17},所以 s1=2s_1 = 2,s2=5s_2 = 5。秘密立刻暴露。 有了误差,四个方程互相"不一致",消元得到的结果会被噪声污染。在 n=2n=2 时还能暴力枚举 172=28917^2 = 289 种可能,但实际的 nn 是几百,枚举量是 qnq^{n} 量级。

第 2 步:加密比特 μ=1\mu = 1。 随机选 r=(1,0,1,1)Tr = (1, 0, 1, 1)^{\mathsf T},也就是取第 1、3、4 个样本相加:

u=ATr=(3+11+27+4+9)=(1620)≡(163)(mod17),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},

v=bTr+8=(8+8+16)+8=40≡6(mod17).v = b^{\mathsf T} r + 8 = (8 + 8 + 16) + 8 = 40 \equiv 6 \pmod{17}.

密文是 (u,v)=((16,3)T,  6)(u, v) = \big((16, 3)^{\mathsf T},\; 6\big)。

第 3 步:解密。 用私钥算

uTs=16⋅2+3⋅5=47≡13(mod17),u^{\mathsf T} s = 16\cdot 2 + 3 \cdot 5 = 47 \equiv 13 \pmod{17},

d=v−uTs=6−13=−7≡10(mod17).d = v - u^{\mathsf T} s = 6 - 13 = -7 \equiv 10 \pmod{17}.

判断规则:Z17\mathbb{Z}_{17} 里离 00 近的是 {13,…,16,0,1,…,4}\{13,\dots,16, 0, 1, \dots, 4\},离 88 近的是 {5,…,12}\{5, \dots, 12\}。d=10d = 10 离 88 只差 22,所以解密为 11 ✓。

验证一下理论:eTr=1+0+1=2e^{\mathsf T} r = 1 + 0 + 1 = 2,确实有

d=eTr+8=2+8=10.d = e^{\mathsf T} r + 8 = 2 + 8 = 10.

对照:加密 μ=0\mu = 0。 用同一个 rr,uu 不变,v=32≡15v = 32 \equiv 15,于是 d=15−13=2d = 15 - 13 = 2,离 00 近,解密为 00 ✓。

为什么总是正确? ee 各分量的绝对值之和是 33,所以对任意 r∈{0,1}4r \in \{0,1\}^4 都有 ∣eTr∣≤3<17/4|e^{\mathsf T} r| \le 3 < 17/4,解密永远不会出错。(已用 Python 枚举全部 242^4 个 rr 和两种比特验证。)

真实参数的规模

这个例子里 n=2n=2,攻击者暴力枚举就能破。ML-KEM-768 相当于 n=768n = 768、q=3329q = 3329,暴力枚举需要 33297683329^{768} 次,而最好的格算法(BKZ)也需要约 21802^{180} 次运算。

3.4 Ring-LWE 与 Module-LWE

普通 LWE 有个大问题:公钥太大。矩阵 AA 有 m×nm \times n 个元素,n=768n = 768 时就是几十万个数,公钥要几百 KB。

Ring-LWE 的想法:让 AA 有结构,用一个多项式代替整个矩阵。

取商环

Rq=Zq[x]/(xn+1),R_q = \mathbb{Z}_q[x] / (x^n + 1),

它的元素是次数 <n< n、系数在 Zq\mathbb{Z}_q 中的多项式,乘法做完后用 xn=−1x^n = -1 化简。用抽象代数的语言说,RqR_q 就是 Z[x]\mathbb{Z}[x] 模掉理想 (q,  xn+1)(q,\; x^n+1) 得到的商环:

Rq  ≅  Z[x]/(q,  xn+1).R_q \;\cong\; \mathbb{Z}[x] / (q,\; x^n + 1).

在 RqR_q 中,"乘以 a(x)a(x)"是 Zq\mathbb{Z}_q-线性映射,对应一个 n×nn\times n 矩阵:

a(x)⋅s(x)⟷(a0−an−1⋯−a1a1a0⋯−a2⋮⋮⋱⋮an−1an−2⋯a0)(s0s1⋮sn−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}.

这种矩阵叫反循环矩阵(negacyclic):每一列都是上一列往下"转一格",转到顶上的元素变号,因为 x⋅xn−1=xn=−1x \cdot x^{n-1} = x^n = -1。整个矩阵只由 nn 个数决定,存储量从 n2n^2 降到 nn。

Ring-LWE

给定 a∈Rqa \in R_q 均匀随机,s,e∈Rqs, e \in R_q 系数都很小,区分 (a,  as+e)(a,\; as + e) 和 (a,  u)(a,\; u)。

为什么用 xn+1x^n + 1? 取 n=2kn = 2^k,此时

xn+1=Φ2n(x)x^n + 1 = \Phi_{2n}(x)

是第 2n2n 个分圆多项式(它的复根恰好是全部 2n2n 次本原单位根 eπi(2j+1)/ne^{\pi i (2j+1)/n})。选它有几个原因:

  1. 在 Q\mathbb{Q} 上不可约(对 Φ2k+1\Phi_{2^{k+1}} 可以对 f(x+1)f(x+1) 用 Eisenstein 判别法,p=2p=2)。于是 Z[x]/(xn+1)\mathbb{Z}[x]/(x^n+1) 是分圆域 Q(ζ2n)\mathbb{Q}(\zeta_{2n}) 的整数环。Lyubashevsky–Peikert–Regev(2010)正是借助这个代数数论结构,把 Ring-LWE 的困难性归约到理想格上的最坏情况困难问题。
  2. 不可约很重要。反例:如果用 xn−1=(x−1)(⋯ )x^n - 1 = (x-1)(\cdots),就有环同态 Zq[x]/(xn−1)→Zq,f(x)↦f(1).\mathbb{Z}_q[x]/(x^n - 1) \to \mathbb{Z}_q, \qquad f(x) \mapsto f(1). 把 b=as+eb = as + e 两边代入 x=1x = 1,得到 b(1)=a(1)s(1)+e(1)b(1) = a(1)s(1) + e(1)。这是只有 1 个未知数的小问题,e(1)e(1) 又比较小,泄露的信息足以发起攻击。
  3. 约化很便宜:xn≡−1x^n \equiv -1,模运算只需把高次项变号加回低次项。而且系数不会在约化中膨胀("扩张因子"小),误差保持很小。
  4. 适合 NTT:当 q≡1(mod2n)q \equiv 1 \pmod{2n}(或 (modn)\pmod n)时,xn+1x^n+1 在 Zq\mathbb{Z}_q 上能分解,乘法可以用 NTT 加速(见 3.6)。

Module-LWE:介于两者之间。 Ring-LWE 的结构太"满",Module-LWE 退回一点:用 k×kk \times k 的环元素矩阵

A∈Rqk×k,s,e∈Rqk,t=As+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}.

这是 RqR_q-模 RqkR_q^k 上的 LWE,所以叫 Module-LWE。好处:

参数集 kk 等效 LWE 维数 nknk 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=256n = 256、q=3329q = 3329。

3.5 Kyber(ML-KEM)的流程

记号:Rq=Zq[x]/(x256+1)R_q = \mathbb{Z}_q[x]/(x^{256}+1),q=3329q = 3329。"小"多项式的系数从中心二项分布 βη\beta_\eta 中采样,取值在 {−η,…,η}\{-\eta, \dots, \eta\},ML-KEM-768 中 η=2\eta = 2。

密钥生成

  1. 随机种子 ρ\rho,用 SHAKE128 把它展开成矩阵 A∈Rqk×k\mathbf{A} \in R_q^{k\times k}(这样公钥只需存 32 字节的 ρ\rho,不用存整个矩阵)。
  2. 采样小的 s,e∈Rqk\mathbf{s}, \mathbf{e} \in R_q^k。
  3. 计算 t=As+e\mathbf{t} = \mathbf{A}\mathbf{s} + \mathbf{e}。
  4. 公钥 pk=(ρ,t)\mathrm{pk} = (\rho, \mathbf{t}),私钥 sk=s\mathrm{sk} = \mathbf{s}。

加密(消息 mm 是 256 比特,看成系数为 0/10/1 的多项式)

  1. 采样小的 r,e1∈Rqk\mathbf{r}, \mathbf{e}_1 \in R_q^k 和小的 e2∈Rqe_2 \in R_q。
  2. 计算 u=ATr+e1,v=tTr+e2+⌈q2⌋⋅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.
  3. 把 u,v\mathbf{u}, v 的系数压缩(只保留高位比特),输出密文 c=(u,v)c = (\mathbf{u}, v)。

解密

v−sTu=eTr+e2−sTe1⏟小噪声  +  ⌈q2⌋⋅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 . 对每个系数四舍五入:接近 00 记为 00,接近 q/2≈1665q/2 \approx 1665 记为 11,就得到 mm。

推导只用了 t=As+e\mathbf{t} = \mathbf{A}\mathbf{s}+\mathbf{e} 和 RqR_q 的交换性:

tTr−sTATr=(As)Tr+eTr−sTATr=eTr.\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}.

这和 3.3 的玩具例子结构完全相同,只是把"整数"换成了"RqR_q 里的多项式",一次加密 256 个比特而不是 1 个。

BobAliceBobAlice采样小的 s, et = A s + e随机选 32 字节 mu = A^T r + e1v = t^T r + e2 + round(q/2) mv - s^T u 四舍五入 得到 m双方用哈希从 m 派生共享密钥 K公钥 (rho, t)密文 (u, v)

从"加密"到"KEM":Fujisaki–Okamoto 变换

上面的方案只能抵抗被动攻击(IND-CPA)。ML-KEM 在外面套了一层 FO 变换:加密用的随机数 r,e1,e2\mathbf{r}, \mathbf{e}_1, e_2 都由 mm 和公钥的哈希确定性地生成;解密方解出 mm 后重新加密一遍,检查是否得到同一个密文,不一致就输出一个伪随机密钥("隐式拒绝")。这样就能抵抗选择密文攻击(IND-CCA2)。

3.6 NTT:用中国剩余定理加速乘法

Kyber 的主要计算量是 RqR_q 中的多项式乘法。直接相乘需要 2562=65536256^2 = 65536 次系数乘法,NTT(数论变换) 可以把它降到 O(nlog⁡n)O(n\log n) 量级。NTT 就是有限域上的 FFT,背后的数学是抽象代数里的中国剩余定理。

中国剩余定理(多项式环版本)

设 FF 是域,f=f1f2⋯frf = f_1 f_2 \cdots f_r,且 fif_i 两两互素。则有环同构 F[x]/(f)  →  ∼    F[x]/(f1)×⋯×F[x]/(fr),g↦(g mod f1,  …,  g mod fr).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). 互素保证了理想 (fi)(f_i) 两两互素((fi)+(fj)=F[x](f_i) + (f_j) = F[x]),这正是 CRT 的条件。

关键点:同构右边的乘法是逐分量的。所以计算 g⋅hg \cdot h 时,可以:

  1. 把 g,hg, h 分别映到右边(正向 NTT);
  2. 逐分量相乘(便宜);
  3. 映回左边(逆向 NTT)。

而第 1、3 步可以像 FFT 那样递归地对半拆分 x2m−c2=(xm−c)(xm+c)x^{2m} - c^2 = (x^m - c)(x^m + c),总共 log⁡n\log n 层。

先看一个小例子:Z17[x]/(x4+1)\mathbb{Z}_{17}[x]/(x^4+1)。

因为 17≡1(mod8)17 \equiv 1 \pmod 8,Z17×\mathbb{Z}_{17}^\times(循环群,阶为 1616)中有 8 次本原单位根,所以 x4+1x^4 + 1 在 Z17\mathbb{Z}_{17} 上完全分解。它的四个根是 2,8,9,152, 8, 9, 15(例如 24=16≡−12^4 = 16 \equiv -1)。于是

Z17[x]/(x4+1)  ≅  Z17[x]/(x−2)×Z17[x]/(x−8)×Z17[x]/(x−9)×Z17[x]/(x−15)  ≅  Z174,\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,

同构映射就是代值 g↦(g(2),g(8),g(9),g(15))g \mapsto \big(g(2), g(8), g(9), g(15)\big)。

取 f=1+2x+x3f = 1 + 2x + x^3,g=3+x2g = 3 + x^2。直接计算(用 x4=−1x^4 = -1,x5=−xx^5 = -x):

fg=3+6x+x2+5x3+x5=3+5x+x2+5x3.fg = 3 + 6x + x^2 + 5x^3 + x^5 = 3 + 5x + x^2 + 5x^3.

用代值验证:

点 aa f(a)f(a) g(a)g(a) f(a)g(a) mod 17f(a)g(a) \bmod 17 (fg)(a)(fg)(a)
22 1313 77 66 66
88 22 1616 1515 1515
99 00 1616 00 00
1515 66 77 88 88

完全吻合。顺便注意 f(9)=0f(9) = 0:ff 不是零多项式,却在一个分量上为零,所以 ff 是这个环里的零因子。这说明 RqR_q 不是整环,和"x4+1x^4+1 在 Z17\mathbb{Z}_{17} 上可约"是一回事。

回到 Kyber:q=3329q = 3329,q−1=3328=28⋅13q - 1 = 3328 = 2^8 \cdot 13。

x256+1=∏i=0127(x2−ζi),ζi=ζ 2 br7(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},

其中 br7(i)\mathrm{br}_7(i) 表示把 ii 的 7 位二进制表示反转(这只是为了 FFT 递归时的顺序)。这 128 个 ζi\zeta_i 恰好是 y128=−1y^{128} = -1 的全部根。由 CRT:

Rq=Zq[x]/(x256+1)  ≅  ∏i=0127Zq[x]/(x2−ζi).R_q = \mathbb{Z}_q[x]/(x^{256}+1) \;\cong\; \prod_{i=0}^{127} \mathbb{Z}_q[x]/(x^2 - \zeta_i).

再进一步:x2−ζix^2 - \zeta_i 在 Zq\mathbb{Z}_q 上不可约。如果 ζi=y2\zeta_i = y^2,那么 yy 的阶就是 512512,而这样的元素不存在。所以每个因子都是一个域 Fq2\mathbb{F}_{q^2},于是

Rq  ≅  Fq2×⋯×Fq2⏟128 个.R_q \;\cong\; \underbrace{\mathbb{F}_{q^2} \times \cdots \times \mathbb{F}_{q^2}}_{128\text{ 个}}.

在 NTT 域里,两个多项式相乘就变成 128 次"模 x2−ζix^2 - \zeta_i 的一次多项式乘法":

(a0+a1x)(b0+b1x)≡(a0b0+ζi a1b1)+(a0b1+a1b0) x(modx2−ζ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}.

工程上的妙处

  • Kyber 规定 A\mathbf{A} 直接在 NTT 域中采样,公钥 t\mathbf{t} 也以 NTT 形式存储,省掉大量正逆变换。
  • ML-DSA 用 q=8380417q = 8380417,它满足 q≡1(mod512)q \equiv 1 \pmod{512},所以 x256+1x^{256}+1 能完全分解成 256 个一次因子,NTT 一路拆到底。
  • 这也解释了为什么 ML-KEM 比 X25519 还快:NTT 和小模数下的整数运算在 CPU 上非常高效。

3.7 ML-DSA 的签名思路(简述)

ML-DSA(Dilithium)采用"带中止的 Fiat–Shamir":

  1. 承诺:随机选小的 y\mathbf{y},计算 w=Ay\mathbf{w} = \mathbf{A}\mathbf{y} 的高位比特 w1\mathbf{w}_1。
  2. 挑战:c=H(消息 ∥ w1)c = H(\text{消息} \,\|\, \mathbf{w}_1),cc 是只有少数系数为 ±1\pm 1 的稀疏多项式。
  3. 响应:z=y+c s1\mathbf{z} = \mathbf{y} + c\,\mathbf{s}_1。
  4. 中止检查:如果 z\mathbf{z} 的系数太大(可能泄露 s1\mathbf{s}_1 的信息),就丢掉重来。通过拒绝采样,z\mathbf{z} 的分布与私钥无关。

验证者检查 Az−c t\mathbf{A}\mathbf{z} - c\,\mathbf{t} 的高位是否等于 w1\mathbf{w}_1,以及 z\mathbf{z} 是否足够小。其安全性依赖 Module-LWE 和 Module-SIS(找短向量 x\mathbf{x} 使 Ax=0\mathbf{A}\mathbf{x} = 0)。

3.8 基于哈希的签名:从 Lamport 到 SPHINCS+

哈希签名的安全性只依赖哈希函数的单向性和抗碰撞性,没有任何代数结构。这是最保守的方案。

Lamport 一次性签名(1979):设 HH 输出 256 比特。

伪造签名需要对某个 yi,by_{i,b} 求哈希原像。但每个密钥只能用一次:签两条消息就会暴露两边的部分私钥,攻击者可以拼出新签名。

改进路线:

Lamport
一次性,签名约 8 KB

Winternitz (WOTS)
哈希链压缩签名

Merkle 树 (XMSS / LMS)
2^h 个一次性密钥
需要记录状态

SPHINCS+ / SLH-DSA
超树 + FORS
无状态


总结

Shor

Grover

量子计算机

RSA / ECC / 配对 SNARK
彻底失效

AES / SHA
安全性减半,加长密钥即可

后量子替代

ML-KEM (Kyber)
密钥交换

ML-DSA (Dilithium)
签名

SLH-DSA (SPHINCS+)
保守签名

Module-LWE
R_q = Z_q[x]/(x^256+1)

NTT = CRT 环同构
快速乘法

只依赖哈希函数

层次 要点
通俗理解 Shor 让 RSA/ECC 归零,Grover 只让 AES 减半;"先存储后解密"使迁移刻不容缓;格密码 = 高维空间里找最近点
实际用处 2024 年 FIPS 203/204/205;Chrome、Cloudflare、Signal、iMessage、OpenSSH 已默认使用混合 ML-KEM;2035 年是 RSA/ECC 的退役线
数学原理 LWE:b=As+eb = As + e,噪声 ee 让线性代数失效;Rq=Zq[x]/(x256+1)R_q = \mathbb{Z}_q[x]/(x^{256}+1) 压缩公钥;NTT 就是 CRT 同构 Rq≅∏Zq[x]/(x2−ζi)R_q \cong \prod \mathbb{Z}_q[x]/(x^2 - \zeta_i)

和抽象代数的联系

  • 商环:Rq=Z[x]/(q,x256+1)R_q = \mathbb{Z}[x]/(q, x^{256}+1)
  • 不可约多项式:xn+1x^n+1 在 Q\mathbb{Q} 上不可约,在 Zq\mathbb{Z}_q 上可约;后者正是 NTT 能用的原因
  • 环同态:代值映射 f↦f(1)f \mapsto f(1) 解释了为什么不能用 xn−1x^n - 1
  • 中国剩余定理:NTT 的全部数学内容
  • 零因子:RqR_q 不是整环,例子中 f(9)=0f(9) = 0
  • 有限域:每个 CRT 分量 Zq[x]/(x2−ζi)≅Fq2\mathbb{Z}_q[x]/(x^2 - \zeta_i) \cong \mathbb{F}_{q^2}