Caloogy 文章
English

中国剩余定理:一个定理撑起半个密码学

日期
2025 年 11 月 11 日
系列
密码学
阅读
3 分钟
主题
CRTChinese Remainder TheoremRing isomorphismRSA

一句话版本

若 m,nm, n 互素,则 Zmn≅Zm×Zn\mathbb{Z}_{mn} \cong \mathbb{Z}_m \times \mathbb{Z}_n 是环同构:一个模 mnmn 的数,和它"模 mm 的余数、模 nn 的余数"这一对数,是一回事。 于是一个大问题可以拆成几个小问题分头算,再拼回来。RSA 加速、Pohlig–Hellman 攻击、全同态加密的 RNS 表示、NTT 快速乘法,背后都是它。

全文分三层:

  1. 通俗理解:韩信点兵
  2. 实际用处:密码学里 CRT 出现的五个地方
  3. 数学原理:环同构、构造性证明、多项式版本,附手算例子

第一层:通俗理解

1.1 韩信点兵

《孙子算经》(约公元 4 世纪)里的题目:

今有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?

答案是 2323。民间口诀叫"韩信点兵":士兵三人一排、五人一排、七人一排,只报每次剩几个人,就能推出总人数(在 105105 以内唯一)。

1.2 一个数,两种"身份证"

00 到 1414 的每个数,都可以用"除以 3 的余数、除以 5 的余数"这一对数来唯一表示:

xx 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
x mod 3x \bmod 3 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2
x mod 5x \bmod 5 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4

15 个数,15 种不同的余数对,一一对应。而且更妙的是:加法和乘法可以分开在两边算。比如 4×7=28≡13(mod15)4 \times 7 = 28 \equiv 13 \pmod{15};用余数对算:

(1,4)×(1,2)=(1⋅1 mod 3, 4⋅2 mod 5)=(1,3),(1, 4) \times (1, 2) = (1 \cdot 1 \bmod 3,\ 4 \cdot 2 \bmod 5) = (1, 3),

查表,(1,3)(1, 3) 对应的正是 1313。

1.3 为什么这很有用

大数运算的代价随位数增长很快(乘法大约是位数的平方)。把一个 2048 位的数拆成两个 1024 位的余数,每边的乘法便宜 4 倍,而且两边可以并行。这就是"分而治之"。


第二层:实际用处

出现的地方 CRT 干了什么 详见
RSA 解密 / 签名加速 把模 n=pqn = pq 的幂运算拆成模 pp、模 qq,快 3 到 4 倍 RSA与欧拉定理
Pohlig–Hellman 攻击 群的阶有小因子时,把离散对数拆碎逐个解,再拼回来 Diffie–Hellman与离散对数
Håstad 广播攻击 同一消息用 e=3e = 3 发给三个人,三个密文用 CRT 拼成整数 m3m^3 RSA与欧拉定理
全同态加密的 RNS 表示 几百位的模数 q=q0q1⋯qLq = q_0 q_1 \cdots q_L 拆成一串 64 位素数,每个都能用机器字直接算;模切换就是"扔掉一个素数" 同态加密
NTT 快速多项式乘法 多项式版本的 CRT:F[x]/(xn−1)≅Fn\mathbb{F}[x]/(x^n - 1) \cong \mathbb{F}^n 后量子密码

此外,素性检验里分析 Carmichael 数、Shamir秘密分享的拉格朗日插值,也是 CRT 的同类思想(拉格朗日插值本身就是多项式环上的 CRT)。

拆开算也带来风险

RSA-CRT 如果只在其中一半出了计算错误,攻击者用一个 gcd⁡\gcd 就能分解模数(Bellcore 故障攻击)。


第三层:数学原理

3.1 定理

设 m1,…,mkm_1, \dots, m_k 两两互素,M=m1⋯mkM = m_1 \cdots m_k。则映射

π:ZM→Zm1×⋯×Zmk,x↦(x mod m1,…,x mod mk)\pi: \mathbb{Z}_M \to \mathbb{Z}_{m_1} \times \cdots \times \mathbb{Z}_{m_k},\qquad x \mapsto (x \bmod m_1, \dots, x \bmod m_k)

是环同构。

证明思路(抽象代数标准做法):

  1. 先看 π~:Z→∏Zmi\tilde\pi: \mathbb{Z} \to \prod \mathbb{Z}_{m_i},它显然是环同态(每个分量都是取模同态);
  2. 核是"同时被所有 mim_i 整除的数",由两两互素,就是 MZM\mathbb{Z};
  3. 由第一同构定理,Z/MZ≅im⁡π~\mathbb{Z}/M\mathbb{Z} \cong \operatorname{im}\tilde\pi;
  4. 两边都有 MM 个元素,单射即满射,所以是同构。

更一般的版本:交换环 RR 中两两互素(Ii+Ij=RI_i + I_j = R)的理想 I1,…,IkI_1, \dots, I_k 满足 R/(I1⋯Ik)≅R/I1×⋯×R/IkR / (I_1 \cdots I_k) \cong R/I_1 \times \cdots \times R/I_k。

3.2 怎么拼回来(构造逆映射)

令 Mi=M/miM_i = M / m_i,求 yi=Mi−1 mod miy_i = M_i^{-1} \bmod m_i(互素保证存在,用扩展欧几里得算法)。则

x=∑iri Mi yi mod M.x = \sum_{i} r_i \, M_i \, y_i \bmod M.

道理:ei=Miyie_i = M_i y_i 满足"模 mim_i 是 11,模其他 mjm_j 是 00",它是第 ii 个分量的"单位向量"。这和Shamir秘密分享里的拉格朗日基多项式 Lj(x)L_j(x) 是完全一样的思路。

3.3 手算例子:韩信点兵

x≡2(mod3)x \equiv 2 \pmod 3,x≡3(mod5)x \equiv 3 \pmod 5,x≡2(mod7)x \equiv 2 \pmod 7

M=105M = 105。

ii mim_i MiM_i Mi mod miM_i \bmod m_i yi=Mi−1y_i = M_i^{-1} ei=Miyie_i = M_i y_i
1 3 35 2 2(2⋅2=4≡12\cdot 2 = 4 \equiv 1) 70
2 5 21 1 1 21
3 7 15 1 1 15

x=2⋅70+3⋅21+2⋅15=140+63+30=233≡23(mod105).x = 2 \cdot 70 + 3 \cdot 21 + 2 \cdot 15 = 140 + 63 + 30 = 233 \equiv 23 \pmod{105}.

检查:23=7⋅3+2=4⋅5+3=3⋅7+223 = 7\cdot 3 + 2 = 4 \cdot 5 + 3 = 3 \cdot 7 + 2。✓

《孙子算经》的口诀"三人同行七十稀,五树梅花廿一枝,七子团圆正半月,除百零五便得知"里的 7070、2121、1515,正是表中的 eie_i。(已用 Python 验算。)

3.4 多项式版本

把 Z\mathbb{Z} 换成 F[x]F[x],把互素的整数换成互素的多项式,定理照样成立。若 f(x)=∏i(x−αi)f(x) = \prod_i (x - \alpha_i),αi\alpha_i 两两不同,则

F[x]/(f)≅F×F×⋯×F,g(x)↦(g(α1),…,g(αn)).F[x]/(f) \cong F \times F \times \cdots \times F,\qquad g(x) \mapsto \big(g(\alpha_1), \dots, g(\alpha_n)\big).

左边的乘法是多项式乘法(卷积,慢);右边是逐点相乘(快)。这正是 FFT / NTT 的代数本质:取 αi\alpha_i 为单位根时,正反两个方向都能用分治在 O(nlog⁡n)O(n \log n) 内完成。


总结

层次 要点
直觉 一个数 = 一组余数;运算可以分开算再拼回
代数 Zmn≅Zm×Zn\mathbb{Z}_{mn} \cong \mathbb{Z}_m \times \mathbb{Z}_n,由第一同构定理得到
构造 找"单位向量" eie_i,和拉格朗日插值同一个思路
应用 RSA 加速、Pohlig–Hellman、Håstad、RNS、NTT