Caloogy 文章
English

同态加密科普

日期
2026 年 4 月 9 日
系列
密码学
阅读
16 分钟
主题
Homomorphic encryptionFHELatticeLWE

一句话版本

同态加密让别人不解密就能直接对密文做运算,而且算出来的密文解密后,恰好等于对明文做同样运算的结果。 用抽象代数的语言说:解密映射 Dec\mathrm{Dec} 在"合法密文"上(近似地)是一个环同态,即 Dec(c1+c2)=Dec(c1)+Dec(c2),Dec(c1⋅c2)=Dec(c1)⋅Dec(c2).\mathrm{Dec}(c_1 + c_2) = \mathrm{Dec}(c_1) + \mathrm{Dec}(c_2),\qquad \mathrm{Dec}(c_1 \cdot c_2) = \mathrm{Dec}(c_1)\cdot \mathrm{Dec}(c_2).

全文分三层:

  1. 通俗理解:不需要任何数学
  2. 实际用处:隐私云计算、医疗与基因、银行联合风控、隐私机器学习、电子投票、私有信息检索,以及业界现状和性能代价
  3. 数学原理:RSA、Paillier、ElGamal、环同态、LWE/RLWE、噪声、模切换、自举、BGV/BFV/CKKS,并附小数字手算例子

第一层:通俗理解

1.1 带着手套操作上锁的箱子

想象一个珠宝商,手下有个工匠,但珠宝商不信任他,怕他偷金子。于是珠宝商这样安排:

  1. 把金料放进一个上了锁的透明手套箱,箱子侧面伸出一副手套。
  2. 工匠把手伸进手套,可以在箱子里把金料熔化、拉丝、焊接成项链。
  3. 但工匠打不开锁,所以碰不到金子,也拿不走。
  4. 做完后箱子还给珠宝商,只有珠宝商有钥匙,打开就得到成品。

对应关系:

比喻 同态加密里的东西
金料 你的私密数据(明文)
上锁的手套箱 密文
工匠 云服务器 / 第三方
隔着手套干活 对密文做运算
钥匙 私钥,只有你有
成品项链 运算结果,解密后才能看到

关键在于:工匠全程都在干活,却从头到尾不知道金子长什么样。普通加密只能做到"锁起来存放和运输",一旦要计算就必须先开锁;同态加密做到了"锁着也能加工"。

1.2 什么叫"直接对密文做运算"

用一个最简单的例子说明。你有两个数 33 和 55,想让云服务器帮你算 3+53+5,但又不想让服务器知道这两个数。

云服务器(没有私钥)

你(有私钥)

加密

上传

下载

明文 3 和 5

密文 Enc(3), Enc(5)

解密得到 8

对密文做'加法'

得到密文 Enc(8)

服务器看到的只是两串乱码,它对乱码执行某种"密文加法",得到第三串乱码。你把第三串乱码解密,得到的恰好是 88。服务器既不知道输入是 33 和 55,也不知道结果是 88。

注意,"密文加法"一般不是把两串数字直接相加。对 Paillier 来说,它是把两个密文相乘;对格密码方案来说,它确实是向量或多项式的相加。具体是什么运算取决于方案,第三层会讲。

1.3 三个级别:PHE、SHE、FHE

任何计算最终都能拆成加法和乘法(在比特上就是异或和与门),所以关键问题是:密文上能做哪些运算,能做多少次。

类型 全称 能做什么 典型例子
PHE Partially Homomorphic Encryption,部分同态 只支持一种运算(只能加,或只能乘),但次数不限 RSA(乘)、ElGamal(乘)、Paillier(加)
SHE Somewhat Homomorphic Encryption,某种程度同态 加法和乘法都支持,但次数有限,做多了就解不开 Gentry 之前的一些格方案、不带自举的 BGV/BFV
FHE Fully Homomorphic Encryption,全同态 加法和乘法都支持,次数不限,可以算任意函数 Gentry 2009 起的方案;带自举的 BGV/BFV/CKKS、TFHE

可以这样记:

历史小插曲

1978 年,RSA 的发明人 Rivest、Adleman 与 Dertouzos 一起提出了"privacy homomorphism"的设想,问能不能对加密数据做任意计算。这个问题悬了 31 年,直到 2009 年 Craig Gentry 在博士论文里给出第一个全同态加密方案。

1.4 为什么叫"同态"

"同态"(homomorphism)是数学词,字面意思是"相同的形状"。在抽象代数里,环同态 φ:R→S\varphi: R \to S 是满足

φ(a+b)=φ(a)+φ(b),φ(ab)=φ(a)φ(b)\varphi(a+b) = \varphi(a) + \varphi(b),\qquad \varphi(ab) = \varphi(a)\varphi(b)

的映射。它把 RR 中的运算"搬运"到 SS 中:先运算再映射,等于先映射再运算。

同态加密说的正是这件事。只是方向通常反过来看:从密文映射到明文的解密保持运算,即

Dec(c1⊕c2)=Dec(c1)+Dec(c2),Dec(c1⊗c2)=Dec(c1)⋅Dec(c2),\mathrm{Dec}(c_1 \oplus c_2) = \mathrm{Dec}(c_1) + \mathrm{Dec}(c_2),\qquad \mathrm{Dec}(c_1 \otimes c_2) = \mathrm{Dec}(c_1)\cdot \mathrm{Dec}(c_2),

其中 ⊕,⊗\oplus, \otimes 是密文空间里对应的运算。换句话说,"在密文世界算"和"在明文世界算"是同一个形状,所以叫同态。

不过严格讲,现代全同态方案里的解密只是一个近似的同态,因为每次运算都会带进一点噪声,这一点在第三层细讲。


第二层:实际用处

2.1 隐私云计算(外包计算)

这是同态加密最原始的动机。公司想用云上的算力,但数据是敏感的(财务、病历、用户行为):

它保护的是"使用中的数据"(data in use)。传输加密(TLS)保护"传输中的数据",磁盘加密保护"静止的数据",计算的那一刻正好是这两者都管不到的空白。

2.2 医疗和基因数据分析

医院和研究机构之间的数据共享受法律严格限制(如美国 HIPAA、欧盟 GDPR)。同态加密可以让:

学术界从 2014 年起每年举办 iDASH 隐私保护基因组分析竞赛,同态加密一直是主要赛道之一,题目包括密文上的全基因组关联分析(GWAS)和逻辑回归训练。

2.3 银行之间的联合风控与反洗钱

洗钱者常把资金拆散在多家银行之间流转,每家银行只看到自己那一段,看不出全貌;但银行之间又不能随便共享客户数据。

同态加密的用法是:各家银行把交易特征加密后交给一个联合分析方,在密文上拼出跨行的资金流图、计算风险评分,最后只把"这个账户可疑"这一结论解密出来。类似的思路也用于联合信用评分和跨机构黑名单查询。实际系统里,同态加密常和安全多方计算(MPC)、私有集合求交(PSI)一起使用。

2.4 隐私机器学习推理

模型在服务器上,数据在用户手里,双方都不想把自己的东西交出去:

  1. 用户把输入(比如一张胸片、一段语音特征)加密后发给服务器;
  2. 服务器用明文模型在密文输入上跑推理,矩阵乘法用同态加法和乘法实现;
  3. 返回加密的预测结果,只有用户能解密。

难点在于激活函数。ReLU、sigmoid 这类非多项式函数不能直接算,常见办法是用低次多项式近似(CKKS 擅长这个),或者用 TFHE 的可编程自举(programmable bootstrapping)直接查表。Zama 的 Concrete ML 就是把 scikit-learn 和 PyTorch 模型自动编译成 FHE 电路的工具。

2.5 电子投票

投票是同态加密最早的成功应用之一,用的是加法同态:

开源的 Helios 投票系统就采用指数 ElGamal(见 3.3 节)来做同态计票,并配合零知识证明,确保每张选票确实是 00 或 11,而不是 Enc(1000)\mathrm{Enc}(1000) 这种作弊票。

2.6 私有信息检索(PIR)

你想从一个公开数据库里查一条记录,又不想让数据库知道你查的是哪一条。

用同态加密的办法:把查询编码成一个加密的"选择向量" Enc(0),…,Enc(1),…,Enc(0)\mathrm{Enc}(0), \dots, \mathrm{Enc}(1), \dots, \mathrm{Enc}(0)(只有第 ii 位是 11),服务器计算

∑jEnc(ej)⋅DBj=Enc(DBi).\sum_j \mathrm{Enc}(e_j)\cdot \mathrm{DB}_j = \mathrm{Enc}(\mathrm{DB}_i).

服务器对每条记录都做了同样的操作,所以完全不知道 ii 是多少。实际方案会把选择向量压缩、递归分层,以降低通信量。

2.7 业界现状

1978RSA 被发现有乘法同态Rivest 等提出 privacyhomomorphism1985ElGamal1999Paillier 加法同态2005Regev 提出 LWE 问题2009Gentry第一个全同态方案(自举)2011-2012BGV、BFV2016TFHE(快速自举)2017CKKS(近似实数运算)2024Apple 在 iOS 18中部署(Live Caller IDLookup)同态加密发展简史

主要开源库

库 维护方 支持的方案 特点
Microsoft SEAL 微软研究院 BFV、BGV、CKKS C++,文档好,入门首选
OpenFHE 社区(PALISADE 的后继,有 DARPA 资助背景) BGV、BFV、CKKS、FHEW、TFHE 类方案 功能最全,支持多种自举与方案切换
TFHE-rs / Concrete Zama(法国) TFHE Rust,布尔和整数电路,可编程自举,也用于区块链上的加密智能合约(fhEVM)
HElib IBM BGV、CKKS 较早的实现
Lattigo Tune Insight / EPFL BFV、BGV、CKKS Go 语言,支持多方(门限)同态
swift-homomorphic-encryption Apple BFV 用于 Apple 自己的 PIR 部署

真实部署:Apple

此外,Google 开源了 FHE 编译器(HEIR 等),Intel 提供了加速库 HEXL,DARPA 的 DPRIVE 项目在资助专用的 FHE 加速芯片。标准化方面,ISO/IEC 18033-6 已经收录了 ElGamal 和 Paillier 这类部分同态方案,全同态方案的标准化(由 HomomorphicEncryption.org 社区推动)还在进行中。

2.8 性能代价

同态加密的主要问题是慢和大。

维度 代价(量级,随方案、参数、硬件差别很大)
计算速度 比明文计算慢大约 10310^3 到 10610^6 倍
密文膨胀 一个 RLWE 密文常有几百 KB 到几 MB
自举 最昂贵的操作。TFHE 单比特自举在 CPU 上是毫秒量级;CKKS 自举一次可能要几秒到几十秒,但一次处理上千个槽
编程难度 只能写成"电路":没有数据相关的分支(if x > 0 必须改写成多项式或查表),循环次数要固定

举个数量级的例子:参数 n=214n = 2^{14}、log⁡2q≈438\log_2 q \approx 438 时,一个密文由两个多项式组成,大小约为

2×214×438 bit≈1.4×107 bit≈1.8 MB.2 \times 2^{14} \times 438 \ \text{bit} \approx 1.4\times 10^{7}\ \text{bit} \approx 1.8\ \text{MB}.

好在借助批处理(batching,见 3.7 节),一个密文可以同时装几千个数做 SIMD 并行运算,摊下来的代价会低很多。

为什么还值得用

在"数据绝对不能离开某个范围"的场景(医疗、金融、政府、跨国数据流动),能用就比不能用好;而且很多应用(PIR、投票、简单统计、小模型推理)只需要浅层电路,开销完全可以接受。


第三层:数学原理

3.1 RSA 的乘法同态

教科书式 RSA:选两个大素数 p,qp, q,令 n=pqn = pq,φ(n)=(p−1)(q−1)\varphi(n) = (p-1)(q-1),取 ee 满足 gcd⁡(e,φ(n))=1\gcd(e, \varphi(n)) = 1,再取 d≡e−1(modφ(n))d \equiv e^{-1} \pmod{\varphi(n)}。

Enc(m)=me mod n,Dec(c)=cd mod n.\mathrm{Enc}(m) = m^e \bmod n,\qquad \mathrm{Dec}(c) = c^d \bmod n.

乘法同态几乎是显然的:

Enc(a)⋅Enc(b)=aebe=(ab)e=Enc(ab)(modn).\mathrm{Enc}(a)\cdot \mathrm{Enc}(b) = a^e b^e = (ab)^e = \mathrm{Enc}(ab) \pmod n.

用抽象代数的语言说,x↦xex \mapsto x^e 是乘法幺半群 (Zn,⋅)(\mathbb{Z}_n, \cdot) 到自身的同态(限制到单位群 Zn×\mathbb{Z}_n^\times 上是群自同构)。但它不保持加法:一般 (a+b)e≠ae+be(a+b)^e \neq a^e + b^e。所以 RSA 只是 PHE。

手算例子:RSA 乘法同态

取 p=5p = 5,q=11q = 11,则 n=55n = 55,φ(n)=40\varphi(n) = 40。取 e=3e = 3,由 3⋅27=81≡1(mod40)3 \cdot 27 = 81 \equiv 1 \pmod{40} 得 d=27d = 27。

  • Enc(2)=23=8\mathrm{Enc}(2) = 2^3 = 8
  • Enc(3)=33=27\mathrm{Enc}(3) = 3^3 = 27
  • 密文相乘:8⋅27=216≡216−3⋅55=51(mod55)8 \cdot 27 = 216 \equiv 216 - 3\cdot 55 = 51 \pmod{55}
  • 直接加密 66:63=216≡51(mod55)6^3 = 216 \equiv 51 \pmod{55},两者一致
  • 解密:5127≡6(mod55)51^{27} \equiv 6 \pmod{55}

所以 Enc(2)⋅Enc(3)=Enc(6)\mathrm{Enc}(2)\cdot\mathrm{Enc}(3) = \mathrm{Enc}(6),即 Enc(2) Enc(3)=Enc(2⋅3)\mathrm{Enc}(2)\,\mathrm{Enc}(3) = \mathrm{Enc}(2\cdot 3)。(已用 Python 验算。)

为什么教科书式 RSA 不安全

  1. 确定性:同一个 mm 每次加密结果都一样。如果明文空间很小(比如投票只有"是/否"),攻击者把所有可能的明文都加密一遍对照就能破解。安全的公钥加密必须是随机化的,才能达到语义安全(IND-CPA)。
  2. 可延展性(malleability):攻击者不知道 mm,但可以把 cc 换成 c⋅2ec \cdot 2^e,于是对方解密得到 2m2m。在"转账金额"这类场景里这是灾难。注意,同态性本身就是可延展性,所以任何同态加密都不可能达到最强的 IND-CCA2 安全,只能追求 IND-CPA。
  3. 小明文攻击:若 e=3e = 3 且 m3<nm^3 < n,则 c=m3c = m^3 在整数上根本没取模,直接开立方根就得到 mm。

实际使用的 RSA 都会先做随机填充(如 OAEP),而填充恰好破坏了同态性。所以 RSA 的同态性更多是教学例子,而不是实用工具。

3.2 Paillier:加法同态

Paillier(1999)是最常用的加法同态方案,基于合数剩余假设:在 Zn2×\mathbb{Z}_{n^2}^\times 中区分 "nn 次幂" 与 "随机元" 是困难的。

密钥生成:取大素数 p,qp, q,n=pqn = pq,λ=lcm⁡(p−1,q−1)\lambda = \operatorname{lcm}(p-1, q-1),g=n+1g = n + 1。定义 L(x)=x−1nL(x) = \dfrac{x - 1}{n},并令 μ=λ−1 mod n\mu = \lambda^{-1} \bmod n。公钥 (n,g)(n, g),私钥 (λ,μ)(\lambda, \mu)。

加密:明文 m∈Znm \in \mathbb{Z}_n,随机选 r∈Zn×r \in \mathbb{Z}_n^\times,

Enc(m;r)=gmrn mod n2.\mathrm{Enc}(m; r) = g^m r^n \bmod n^2.

解密:

Dec(c)=L ⁣(cλ mod n2)⋅μ mod n.\mathrm{Dec}(c) = L\!\left(c^\lambda \bmod n^2\right)\cdot \mu \bmod n.

为什么能解密:

加法同态:

Enc(m1;r1)⋅Enc(m2;r2)=gm1+m2(r1r2)n=Enc(m1+m2; r1r2)(modn2).\mathrm{Enc}(m_1; r_1)\cdot\mathrm{Enc}(m_2; r_2) = g^{m_1+m_2}(r_1 r_2)^n = \mathrm{Enc}(m_1 + m_2;\ r_1 r_2) \pmod{n^2}.

密文乘法对应明文加法。顺带还有数乘:Enc(m)k=Enc(km)\mathrm{Enc}(m)^k = \mathrm{Enc}(km)。所以 Paillier 能算"加密数据的线性组合",比如加权求和、平均值,但不能算两个密文明文的乘积。

群同态视角

映射 Zn×Zn×→Zn2×\mathbb{Z}_n \times \mathbb{Z}_n^\times \to \mathbb{Z}_{n^2}^\times,(m,r)↦gmrn(m, r) \mapsto g^m r^n 是一个群同构:左边的运算是 (m1,r1)⋅(m2,r2)=(m1+m2, r1r2)(m_1, r_1)\cdot(m_2, r_2) = (m_1 + m_2,\ r_1 r_2),右边是乘法。两边的阶都是 nφ(n)n\varphi(n)。Paillier 的加法同态就是这个同构的直接推论。

手算例子:Paillier 加法同态

取 p=5p = 5,q=7q = 7,则 n=35n = 35,n2=1225n^2 = 1225,g=36g = 36,λ=lcm⁡(4,6)=12\lambda = \operatorname{lcm}(4, 6) = 12。 由于 gλ=(1+n)12≡1+12ng^\lambda = (1+n)^{12} \equiv 1 + 12n,L(gλ)=12L(g^\lambda) = 12,所以 μ=12−1 mod 35=3\mu = 12^{-1} \bmod 35 = 3(因为 12⋅3=36≡112 \cdot 3 = 36 \equiv 1)。

加密 m1=4m_1 = 4,取 r1=2r_1 = 2:

  • g4≡1+4⋅35=141(mod1225)g^{4} \equiv 1 + 4\cdot 35 = 141 \pmod{1225}
  • 235≡18(mod1225)2^{35} \equiv 18 \pmod{1225}
  • c1=141⋅18=2538≡88(mod1225)c_1 = 141 \cdot 18 = 2538 \equiv 88 \pmod{1225}

加密 m2=6m_2 = 6,取 r2=3r_2 = 3:

  • g6≡1+6⋅35=211(mod1225)g^{6} \equiv 1 + 6\cdot 35 = 211 \pmod{1225}
  • 335≡607(mod1225)3^{35} \equiv 607 \pmod{1225}
  • c2=211⋅607=128077≡677(mod1225)c_2 = 211 \cdot 607 = 128077 \equiv 677 \pmod{1225}

密文相乘:c=c1c2=88⋅677=59576≡776(mod1225)c = c_1 c_2 = 88 \cdot 677 = 59576 \equiv 776 \pmod{1225}

解密 cc:

  • 77612≡526(mod1225)776^{12} \equiv 526 \pmod{1225}
  • L(526)=526−135=15L(526) = \dfrac{526 - 1}{35} = 15
  • 15⋅3=45≡10(mod35)15 \cdot 3 = 45 \equiv 10 \pmod{35}

得到 10=4+610 = 4 + 6。作为对照,单独解密 c1c_1:8812≡45688^{12} \equiv 456,L(456)=13L(456) = 13,13⋅3=39≡413\cdot 3 = 39 \equiv 4,正确。

两点补充(均已用 Python 验算):

  • 数乘:c13≡372(mod1225)c_1^3 \equiv 372 \pmod{1225},解密得 12=3⋅412 = 3 \cdot 4。
  • 明文是在 Z35\mathbb{Z}_{35} 里加的:Enc(30)⋅Enc(10)\mathrm{Enc}(30)\cdot\mathrm{Enc}(10) 解密得 40 mod 35=540 \bmod 35 = 5,所以实际使用时 nn 必须远大于可能的结果。

3.3 ElGamal:乘法同态,以及"指数"版本的加法同态

设 G=⟨g⟩G = \langle g \rangle 是一个离散对数困难的循环群(如 Zp×\mathbb{Z}_p^\times 的子群或椭圆曲线群)。私钥 xx,公钥 h=gxh = g^x。

Enc(m;k)=(gk, mhk),Dec(c1,c2)=c2⋅c1−x.\mathrm{Enc}(m; k) = (g^k,\ m h^k),\qquad \mathrm{Dec}(c_1, c_2) = c_2 \cdot c_1^{-x}.

它天然是随机化的(每次选新的 kk),在 DDH 假设下是 IND-CPA 安全的。分量相乘得到

(gk1,m1hk1)⋅(gk2,m2hk2)=(gk1+k2, m1m2 hk1+k2)=Enc(m1m2; k1+k2),(g^{k_1}, m_1 h^{k_1})\cdot (g^{k_2}, m_2 h^{k_2}) = (g^{k_1+k_2},\ m_1 m_2\, h^{k_1+k_2}) = \mathrm{Enc}(m_1 m_2;\ k_1 + k_2),

所以 ElGamal 是乘法同态的。

手算例子:ElGamal

取 p=23p = 23,g=5g = 5(Z23×\mathbb{Z}_{23}^\times 的生成元),私钥 x=6x = 6,公钥 h=56≡8(mod23)h = 5^6 \equiv 8 \pmod{23}。

  • Enc(3;k=2)=(52, 3⋅82)≡(2, 8)\mathrm{Enc}(3; k=2) = (5^2,\ 3\cdot 8^2) \equiv (2,\ 8)
  • Enc(4;k=7)=(57, 4⋅87)≡(17, 2)\mathrm{Enc}(4; k=7) = (5^7,\ 4\cdot 8^7) \equiv (17,\ 2)
  • 分量相乘:(2⋅17, 8⋅2)≡(11, 16)(2\cdot 17,\ 8 \cdot 2) \equiv (11,\ 16)
  • 解密:116≡911^6 \equiv 9,9−1≡189^{-1} \equiv 18,16⋅18=288≡12(mod23)16 \cdot 18 = 288 \equiv 12 \pmod{23}

得到 12=3⋅412 = 3 \cdot 4。(已用 Python 验算。)

指数 ElGamal:把明文放到指数上,加密 gmg^m 而不是 mm:

Enc(m;k)=(gk, gmhk).\mathrm{Enc}(m; k) = (g^k,\ g^m h^k).

这样相乘得到 gm1+m2g^{m_1+m_2},就变成了加法同态。代价是解密只能得到 gmg^m,还要再解一个离散对数才能拿到 mm,所以只适合 mm 很小的情况。投票计票正好满足这一点(总票数不超过选民人数),这就是 Helios 的做法。

PHE 的共同局限

RSA、Paillier、ElGamal 都只有一种运算,而且安全性都基于大整数分解或离散对数,会被量子计算机上的 Shor 算法攻破。下面的格方案同时解决了这两个问题。

3.4 环同态,以及加密为什么只是"近似环同态"

回顾定义:环 R,SR, S 之间的映射 φ:R→S\varphi: R \to S 若满足

φ(a+b)=φ(a)+φ(b),φ(ab)=φ(a)φ(b),φ(1)=1,\varphi(a + b) = \varphi(a) + \varphi(b),\qquad \varphi(ab) = \varphi(a)\varphi(b),\qquad \varphi(1) = 1,

就称为环同态。

为什么想要环同态:任何函数 f:F2k→F2f: \mathbb{F}_2^k \to \mathbb{F}_2 都可以写成 F2\mathbb{F}_2 上的多项式(加法 == 异或,乘法 == 与门),对 Zt\mathbb{Z}_t 上的函数也类似。若解密 Dec\mathrm{Dec} 是环同态,那么对任意多项式 PP,

Dec(P(c1,…,ck))=P(Dec(c1),…,Dec(ck)).\mathrm{Dec}\big(P(c_1, \dots, c_k)\big) = P\big(\mathrm{Dec}(c_1), \dots, \mathrm{Dec}(c_k)\big).

即"在密文上算 PP"等于"在明文上算 PP",这就能算任意函数,也就是全同态。

为什么不能真的是环同态:如果 Enc\mathrm{Enc} 本身是一个确定性的环同态 φ:Zt→S\varphi: \mathbb{Z}_t \to S,那么攻击者可以拿公开的运算做代数攻击。比如环同态必然满足 φ(1)=1S\varphi(1) = 1_S,而 1S1_S 是公开的,于是攻击者能自己算出 φ(2)=1S+1S\varphi(2) = 1_S + 1_S、φ(3)=1S+1S+1S\varphi(3) = 1_S + 1_S + 1_S……把所有明文的密文列成一张表,拿到任何密文一查便知,毫无安全性可言。用抽象代数的话说,由第一同构定理 im⁡φ≅Zt/ker⁡φ\operatorname{im}\varphi \cong \mathbb{Z}_t/\ker\varphi,像的结构完全由公开的代数数据决定。

解决办法:加入噪声。现代方案中,

真正保持运算的是相位(phase)映射,它是一个精确的同态;而"四舍五入"只在噪声足够小的时候才和运算相容。所以说加密是一个近似环同态:只要噪声没长太大,同态性就成立。

3.5 LWE 与 RLWE

LWE 问题(Learning With Errors,Regev 2005):取模数 qq,秘密向量 s∈Zqns \in \mathbb{Z}_q^n。给你很多组

(ai, bi=⟨ai,s⟩+ei mod q),(a_i,\ b_i = \langle a_i, s\rangle + e_i \bmod q),

其中 aia_i 均匀随机,eie_i 是很小的随机误差。要求找出 ss(搜索版本),或者区分这些 (ai,bi)(a_i, b_i) 和均匀随机的数对(判定版本)。

一个最小的 LWE 加密(对称密钥,加密一个比特 m∈{0,1}m \in \{0, 1\}):令 Δ=⌊q/2⌋\Delta = \lfloor q/2 \rfloor,

Enc(m)=(a, b)=(a, ⟨a,s⟩+e+Δm),相位 φs(a,b)=b−⟨a,s⟩=Δm+e.\mathrm{Enc}(m) = (a,\ b) = \big(a,\ \langle a, s\rangle + e + \Delta m\big),\qquad \text{相位 } \varphi_s(a, b) = b - \langle a, s\rangle = \Delta m + e.

解密时看相位离 00 近还是离 Δ\Delta 近。关键观察:相位映射 φs\varphi_s 是 Zq\mathbb{Z}_q-线性的(模同态),所以两个密文相加,相位也相加:

φs(c1+c2)=Δ(m1+m2)+(e1+e2).\varphi_s(c_1 + c_2) = \Delta(m_1 + m_2) + (e_1 + e_2).

手算例子:LWE 上的同态加法(模 2 加法)

取 q=97q = 97,Δ=48\Delta = 48,秘密 s=(5,11)s = (5, 11)。

加密 m1=1m_1 = 1,取 a=(23,40)a = (23, 40),e1=2e_1 = 2: ⟨a,s⟩=115+440=555≡70\langle a, s\rangle = 115 + 440 = 555 \equiv 70,b=70+2+48=120≡23b = 70 + 2 + 48 = 120 \equiv 23,即 c1=((23,40), 23)c_1 = \big((23, 40),\ 23\big)。 相位 =23−70≡50=48+2= 23 - 70 \equiv 50 = 48 + 2,靠近 Δ\Delta,解密为 11。

加密 m2=1m_2 = 1,取 a=(61,7)a = (61, 7),e2=−3e_2 = -3: ⟨a,s⟩=305+77=382≡91\langle a, s\rangle = 305 + 77 = 382 \equiv 91,b=91−3+48=136≡39b = 91 - 3 + 48 = 136 \equiv 39,即 c2=((61,7), 39)c_2 = \big((61, 7),\ 39\big)。 相位 =45=48−3= 45 = 48 - 3,解密为 11。

相加:c1+c2=((84,47), 62)c_1 + c_2 = \big((84, 47),\ 62\big)。 ⟨(84,47),s⟩=420+517=937≡64\langle (84, 47), s\rangle = 420 + 517 = 937 \equiv 64,相位 =62−64≡−2≡95= 62 - 64 \equiv -2 \equiv 95。 −2-2 离 00 近,解密为 00,而 1⊕1=01 \oplus 1 = 0,正确。

这里 2Δ=96≡−1(mod97)2\Delta = 96 \equiv -1 \pmod{97},所以相位等于 −1+e1+e2=−2-1 + e_1 + e_2 = -2。噪声从 ∣e∣≤3|e| \le 3 涨到了 22 再加取整误差,只要总噪声的绝对值不超过 q/4≈24q/4 \approx 24,解密就是对的。(已用 Python 验算。)

RLWE(Ring-LWE,Lyubashevsky–Peikert–Regev 2010):把向量换成多项式环

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

样本变成 (a, b=a⋅s+e)∈Rq2(a,\ b = a\cdot s + e) \in R_q^2,其中 a,s,ea, s, e 都是多项式,ee 的系数很小。好处有两个:

为什么是 xn+1x^n + 1:当 nn 是 22 的幂时,xn+1=Φ2n(x)x^n + 1 = \Phi_{2n}(x) 是第 2n2n 个分圆多项式,在 Q\mathbb{Q} 上不可约(Eisenstein 判别法作用在 x↦x+1x \mapsto x+1 后的多项式上)。由于 xn≡−1x^n \equiv -1,这个商环里的乘法是"负循环卷积",计算方便,而且它的几何性质(典范嵌入)很好,能保证噪声增长可控。这正是抽象代数里的商环 F[x]/(f)F[x]/(f)。

3.6 噪声增长、模切换、自举

密文乘法与"代值同态"

在 RLWE 方案中,可以把一个密文 (c0,c1)(c_0, c_1) 看成关于未知量 yy 的一次多项式 c(y)=c0+c1y∈Rq[y]c(y) = c_0 + c_1 y \in R_q[y]。解密的第一步就是代入 y=sy = s:

evs:Rq[y]→Rq,c(y)↦c(s)=c0+c1s.\mathrm{ev}_s: R_q[y] \to R_q,\qquad c(y) \mapsto c(s) = c_0 + c_1 s.

这正是抽象代数里的代值同态(evaluation homomorphism),它是一个精确的环同态。于是两个密文的乘积就定义为多项式乘积:

c(y)⋅c′(y)=c0c0′+(c0c1′+c1c0′) y+c1c1′ y2,c(y)\cdot c'(y) = c_0c_0' + (c_0c_1' + c_1c_0')\,y + c_1c_1'\, y^2,

它代入 ss 后恰好等于 c(s)⋅c′(s)c(s)\cdot c'(s)。乘完以后密文变成 yy 的二次式(三个分量),再用重线性化(relinearization,借助公开的 s2s^2 的加密,即 key-switching key)把它变回一次式。

噪声如何增长:以 BGV 风格为例,设相位 c(s)=m+tec(s) = m + t e(明文在"低位",模 tt 读出)。

运算 相位 噪声大小
加法 (m+m′)+t(e+e′)(m + m') + t(e + e') 相加:∣e∣+∣e′∣\lvert e\rvert + \lvert e' \rvert
乘法 mm′+t (me′+m′e+tee′)mm' + t\,(me' + m'e + t ee') 大约相乘:∼t ∣e∣∣e′∣\sim t\,\lvert e\rvert \lvert e' \rvert

加法让噪声线性增长,乘法让噪声平方级增长。连续做 LL 层乘法,噪声大约变成 B2LB^{2^L},指数爆炸。一旦噪声超过 q/2q/2 量级,取模就会"绕回",解密出错。这就是 SHE 只能做有限次乘法的原因。

模切换(modulus switching,BGV 的核心技巧):乘完一次后,把整个密文按比例缩小,

c ↦ c′=⌊q′q c⌉,q′<q.c \ \mapsto\ c' = \Big\lfloor \tfrac{q'}{q}\, c \Big\rceil,\qquad q' < q.

噪声也随之缩小 q′/qq'/q 倍,而(经过适当的修正)明文不变。打个比方:噪声的绝对大小被压回原来的量级,代价是模数变小、"剩余空间"变少。实践中取 q=q0q1⋯qLq = q_0 q_1 \cdots q_L 为一串素数的乘积,每层乘法后"扔掉"一个素数,噪声从指数增长变成线性于层数 LL。这串素数的表示用的就是中国剩余定理(RNS 表示),也是抽象代数的内容。

乘法

模切换

乘法

模切换

自举

新鲜密文
噪声很小
模数 q_L

噪声变大

噪声压回
模数降到 q_(L-1)

...

模数 q_0
没有层数了

Gentry 的自举(bootstrapping):层数用完了怎么办?Gentry 的想法是"用同态的方式运行解密算法":

  1. 事先把私钥 ss 用它自己(或另一把公钥)加密,公开 Enc(s)\mathrm{Enc}(s),称为自举密钥。
  2. 拿到一个噪声快满的密文 cc。服务器把 cc 的每一位当作常数,把 Enc(s)\mathrm{Enc}(s) 当作加密输入,同态地计算解密电路 Dec(⋅,c)\mathrm{Dec}(\cdot, c): Eval(Dec(⋅, c), Enc(s))=Enc(Dec(s,c))=Enc(m).\mathrm{Eval}\big(\mathrm{Dec}(\cdot,\ c),\ \mathrm{Enc}(s)\big) = \mathrm{Enc}\big(\mathrm{Dec}(s, c)\big) = \mathrm{Enc}(m).
  3. 结果仍然是 mm 的密文,但它的噪声只来自"计算解密电路"这一步,与原来 cc 里的噪声无关。

只要方案能同态地计算自己的解密电路并且还剩至少一次乘法的余量(称为 bootstrappable),就可以无限次"刷新"密文,从 SHE 升级为 FHE。

两个细节

  • 公开 Enc(s)\mathrm{Enc}(s)(用 ss 自己加密 ss)需要额外的循环安全(circular security)假设,目前没有被证明,但也没有已知攻击。
  • 用手套箱比喻:箱子 A 里的东西快看不清了,就把整个箱子 A 放进一个新的干净箱子 B,再把 A 的钥匙也锁进 B(钥匙是加密的,没人能直接用),然后隔着 B 的手套用 A 的钥匙打开 A。东西就到了干净的箱子 B 里,全程没人见到明文。

3.7 BGV、BFV、CKKS(以及 TFHE)的区别

三大主流 RLWE 方案的密文都在 Rq=Zq[x]/(xn+1)R_q = \mathbb{Z}_q[x]/(x^n + 1) 上,区别在于明文放在相位的哪个位置:

方案 相位 c0+c1sc_0 + c_1 s 的形状 明文空间 适合做什么
BGV(2011) m+t em + t\,e,明文在低位 Rt=Zt[x]/(xn+1)R_t = \mathbb{Z}_t[x]/(x^n + 1),精确整数运算 精确的模 tt 整数运算;靠模切换管理噪声
BFV(2012) Δm+e\Delta m + e,Δ=⌊q/t⌋\Delta = \lfloor q/t \rfloor,明文在高位 同样是 RtR_t,精确整数运算 精确整数运算;"尺度不变",实现较简单(SEAL、Apple 用的就是它)
CKKS(2017) Δm+e\Delta m + e,但把 ee 视为近似误差 复数(实数)向量,近似运算 浮点数计算、机器学习、统计;乘法后用 rescale 除以 Δ\Delta
TFHE / FHEW LWE 样本,明文是比特或小整数 {0,1}\{0,1\} 或 Zt\mathbb{Z}_t(tt 很小) 任意布尔电路、比较、查表;每个门都自举,自举极快

格上的困难问题 LWE / RLWE

精确整数运算

近似实数运算

比特 / 小整数运算

BGV:明文在低位
模切换

BFV:明文在高位
尺度不变

CKKS:误差当作精度损失
rescale

TFHE / FHEW:
每次运算都快速自举
可编程自举 = 查表

CKKS 的核心想法:浮点运算本来就有舍入误差,那就干脆把加密噪声也当成舍入误差的一部分。明文 mm 是"真实值乘以缩放因子 Δ\Delta 再取整",解密得到的是 m+em + e,只要 ee 相对于 Δ\Delta 很小,就只是丢了几位精度。乘法后相位变成 Δ2mm′+⋯\Delta^2 m m' + \cdots,用 rescale(除以 Δ\Delta 并降低模数)恢复尺度,这和模切换是同一个操作。

批处理(SIMD)与中国剩余定理:对 BGV/BFV,若素数 t≡1(mod2n)t \equiv 1 \pmod{2n},则 Zt\mathbb{Z}_t 中含有本原 2n2n 次单位根 ζ\zeta,于是 xn+1x^n + 1 在 Zt[x]\mathbb{Z}_t[x] 上分裂为 nn 个一次因子,由中国剩余定理得

Rt=Zt[x]/(xn+1)  ≅  ∏i=1nZt[x]/(x−ζ2i−1)  ≅  Ztn.R_t = \mathbb{Z}_t[x]/(x^n + 1) \;\cong\; \prod_{i=1}^{n} \mathbb{Z}_t[x]/(x - \zeta^{2i-1}) \;\cong\; \mathbb{Z}_t^n.

这个同构是环同构,所以 RtR_t 里的一次乘法就等于 nn 个槽里各自做一次乘法。一个密文就能同时处理 nn 个数(n=214n = 2^{14} 时是 1638416384 个)。CKKS 用的是类似的想法:通过典范嵌入 R→CnR \to \mathbb{C}^{n} 把 n/2n/2 个复数装进一个多项式。

3.8 小结:从抽象代数看同态加密

抽象代数概念 在同态加密里的角色
群同态 / 环同态 同态性的定义本身;RSA、ElGamal 是乘法群同态,Paillier 是群同构
商环 F[x]/(f)F[x]/(f) 密文与明文所在的环 Zq[x]/(xn+1)\mathbb{Z}_q[x]/(x^n + 1)
代值同态 evs\mathrm{ev}_s 解密的第一步 c0+c1sc_0 + c_1 s,也解释了密文乘法
不可约多项式 xn+1=Φ2nx^n + 1 = \Phi_{2n} 不可约,保证环的结构良好
中国剩余定理 批处理 Rt≅ZtnR_t \cong \mathbb{Z}_t^n;RNS 表示与模切换
理想与核 若 Enc\mathrm{Enc} 是精确同态,核与像的结构会泄露信息,所以必须加噪声

延伸阅读