摘要
自举(Bootstrapping)是全同态加密(Fully Homomorphic Encryption, FHE)中经常使用的术语。熟悉 FHE 的人都知道,自举是 FHE 方案中最复杂且计算密集的部分。然而,只有极少数非 FHE 专家真正理解自举操作的本质,以及不同的自举方法及其各自的权衡取舍。本文的目标是提供对常见自举方法的高层次介绍,并使用 OpenFHE 和 HElib 这两个开源库的现有实现来评估它们的性能。
本文的性能评估表明,在 Cheon-Kim-Kim-Song (CKKS) 方案中,自举操作具有最高的吞吐量,并能高效地对实数向量进行高精度计算,这在机器学习应用中尤为重要。而 Ducas-Micciancio (DM) 和 Chillotti-Gama-Georgieva-Izabachene (CGGI) 方案则实现了最低的延迟(通常用于小整数或 small-precision fixed-point numbers 低精度定点数),并通过查找表(Lookup Tables)提供了可编程自举(Programmable Bootstrapping)的能力,使其能够评估任意函数。Brakerski-Gentry-Vaikuntanathan (BGV) 和 Brakerski/Fan-Vercauteren (BFV) 方案在处理小整数或有限域元素的向量时,相较于 DM/CGGI,具有更高的自举吞吐量,但它们不支持可编程自举。
本文的目标受众是任何对 FHE 感兴趣的人。Duality团队计划持续更新本论文,以纳入新的自举研究成果。
1. 引言
自举(Bootstrapping)是全同态加密(FHE)中经常使用的术语。任何阅读过 FHE 入门资料的人都知道,自举是 FHE 方案中最复杂且计算最密集的部分。然而,除了研究该领域的密码学家之外,很少有人真正理解自举操作的本质,以及不同的自举方法及其各自的权衡取舍。
本文的目标是揭开自举的神秘面纱,纠正该领域中常见的误解,并对 FHE 方案中可用的自举方法进行高层次的比较,以便读者能够做出明智的决策,决定何时以及如何部署 FHE 实现。
本文首先简要介绍同态加密(Homomorphic Encryption, HE),并强调其关键概念和历史里程碑。同态加密是一种加密技术,它允许对密文进行计算,而无需访问秘密密钥。全同态加密(FHE)是最通用的同态加密形式,它可以用于对密文执行任意的程序或计算。
FHE 的概念最早由 Rivest、Adleman 和 Dertouzos 于 1978 年提出(值得注意的是,前两位作者正是著名 RSA 方案的共同作者)[RAD78]。在描述同态加密时,他们使用了“隐私同态(privacy homomorphisms)”这一术语,并提出了以下问题:“是否有可能实现一个操作集合丰富且高度安全的隐私同态?(it remains to be seen whether it is possible to
have a privacy homomorphism with a large set of operations which is highly secure)”[RAD78]。
这个问题在随后的 30 年里一直未能得到解决,直到 2008 年年底,时任斯坦福大学博士生的 Craig Gentry 提出了第一个 FHE 方案 [Gen09]。这一突破不仅在密码学领域意义重大,在理论计算机科学中也具有里程碑式的贡献,而自举正是该方案的关键组成部分。
为了介绍自举,本文将尝试回答以下三个基本问题:
- 1)What:何为自举?
- 2)Why:为何需要自举?
- 3)How:自举工作原理?
1.1 What:何为自举?
一个好的起点是查看《牛津词典》中对“bootstrapping”的定义:其被定义为“pulling yourself up by your (own) bootstraps”(依靠自身拉起自己)。在全同态加密(FHE)中,当我们说某个 FHE 方案是“可自举的(bootstrappable)”时,意味着它除了能够同态地评估至少一个额外的运算外,还能同态地评估其自身的解密过程 [Gen09]。
如上图所示,在传统意义上,执行解密需要一个密文和一个私钥 s k sk sk 作为输入,并生成明文作为输出。然而,在 FHE 中,进行的是解密过程的同态计算,即自举(bootstrapping),其输入是一个加密的私钥和一个密文,并生成一个“等效”的密文,使其能够继续进行同态计算。这个加密的私钥通常被称为自举密钥(bootstrapping key)或刷新密钥(refreshing key),由该私钥持有者提供,并作为公钥的一部分公开——基于的是circular security循环安全假设。
1.2 Why:为何需要自举?
所有常见的 FHE 方案都基于带噪加密(noisy encryption),其中的噪声保证了初始加密的安全性。然而,在进行同态计算时,密文中的噪声会不断增加,从而降低其计算能力(即computational budget计算预算)。自举的主要用途是将“已耗尽(exhausted)”的密文转换为“等效”的、但 已刷新(refreshed) 的密文。 【所谓“等效”,是指加密相同的消息,但具有更小的噪声幅度。】
其中:
- exhausted已耗尽密文:由于噪声过大,无法继续进行同态计算。
- refreshed已刷新密文:噪声较低,可以继续执行同态计算。
自举的另一个重要作用是在自举过程中对加密消息执行一个函数计算。在这种情况下,自举的输出密文加密的不是原始明文,而是明文的某个函数值,同时减少输入密文中的噪声。这种自举方式被称为功能性自举(functional bootstrapping)或可编程自举(programmable bootstrapping)。
1.3 How:自举工作原理?
所有常见的自举方法都遵循 Craig Gentry 提出的 “自举蓝图”,即 同态评估自身的解密过程 。然而,不同 FHE 方案采用的自举机制有所不同。
在接下来的部分,将描述以下 FHE 方案中的自举机制:
- DM (FHEW) / CGGI (TFHE) 方案 [DM15, CGGI16, CGGI20]
- CKKS 方案 [CKKS17]
- BGV / BFV 方案 [Bra12, BGV14, FV12]
本文将重点比较它们的主要区别,并基于 OpenFHE 库 [ABBB+22] 的实验结果以及同行评审的科学文献中的数据对它们的性能进行评估。此外,还将提供一些实际的选型建议。
值得注意的是,截至本文撰写(2023年8月)时,OpenFHE 已实现了 CKKS、DM 和 CGGI 方案的自举,但 BFV/BGV 方案的自举仍在开发中,未来的 OpenFHE 版本将会支持它们。
2. DM/CGGI 密码系统中的自举
2.1 DM密码系统
Ducas-Micciancio (DM) 方案(也称为 FHEW)是第一个能在不到 1 秒内完成自举的 FHE 方案 [DM15],远远快于基于 Gentry 原始方案的实现(单次自举需要长达 30 分钟)[GH11]。DM 方案的主要目标是以最小的延迟评估一个基本的自举计算——布尔 NAND 门。由于 NAND 是 complete boolean gate 完全布尔门,它可以用于构造任意的布尔电路。同样,其他布尔门(如 AND、OR、XOR)也能以相同的计算成本进行评估 [MP21],这使得布尔电路计算更加高效。
正如前文所述,自举本质上是对解密函数的同态计算。在同态加密方案中,解密过程涉及:
- 计算一个线性函数(密文与加密的私钥的乘积)。
- 进行四舍五入(rounding),以提取最终的明文。
DM 方案采用两种不同的技术来评估这两个步骤:
- 线性函数计算:使用一个噪声增长较小的中间密码系统,累积密文与加密私钥位(encrypted bits of the secret key)的乘积。
- 四舍五入:通过查找表(Lookup Table, LUT) 来提取线性函数结果的最高有效位(MSB)。
2.2 CGGI (TFHE)密码系统
Chillotti-Gama-Georgieva-Izabachene (CGGI) 方案是DM 方案的更高效变体,优化了内存使用,并引入了新的自举技术,使其延迟降低到不到 0.1 秒。
与 DM 方案类似,CGGI 方案的基本设计相同,但:
- 安全性更强(采用binary secret distribution二进制秘密分布)。
- 使用更优化的累加器(accumulator),实现更快的自举。
后来的研究 [MP21] 发现,在相同的安全参数下:
- CGGI 在二进制和三进制秘密上比 DM 更快,且占用更少的内存。
- DM 在更大私钥分布(higher secret key distributions)时表现更优。
2.3 DM / CGGI 方案的独特特性
DM 和 CGGI 方案的一个独特特性是:
- 它们能够在自举过程中评估任意函数。这可以通过查找表实现,即用函数值替换原始明文的比特。
这种能力被称为:
- 功能性自举(functional bootstrapping)
- 或 可编程自举(programmable bootstrapping) [CJP21, LMP22]
在所有 FHE 方案中,只有 DM 和 CGGI 具备完整的可编程自举能力。其它 FHE 方案虽然也可以在自举过程中评估某些特殊函数,但无法实现完全的可编程性。
2.4 DM / CGGI 方案的挑战
DM 和 CGGI 方案的主要挑战在于:
- 高精度输入的可编程自举
- 这些方案本质上适用于布尔数据(0 和 1),并能扩展到支持稍大的明文空间(3-8 比特)。
- 但如果继续增加明文空间,每增加 1 比特,运行时间几乎需要翻倍,这使得高精度计算变得不切实际。
近期研究表明,某些函数的计算成本可从指数级降低至线性增长(与精度相关),但更一般的函数仍然计算成本较高 [CLOT21, LMP22]。
2.5 DM / CGGI 方案小结
DM / CGGI 方案小结:
- DM(FHEW):首次实现了亚秒级自举,专注于最低延迟计算。
- CGGI(TFHE):优化了 DM 方案,速度更快、内存占用更低,但在某些大密钥分布场景下不如 DM。
- 独特性:DM/CGGI 具备可编程自举能力,是当前唯一可在自举过程中评估任意函数的 FHE 方案。
- 挑战:扩展到更高精度的计算仍面临挑战,尤其是在高比特明文的情况下。
2.6 新的自举方法
Lee 等人 [LMK+23] 在 OpenFHE 中提出并实现了一种显著改进的 DM 方案变体。与 CGGI 方案相比,该变体在多个方面表现更优:
- 更小的自举密钥(占用更少的内存),即使在小秘密的情况下也是如此。
- 更小的累加器噪声,优于 DM 和 CGGI 方案。
- 更快的运行时间:在二进制(binary)和三进制(ternary)秘密的情况下,其运行时间与 CGGI 相当;在更大的秘密场景下,其速度比 CGGI 更快。
- 更适用于门限(多方)FHE 方案,因为这些方案通常使用更大的秘密。
从 OpenFHE v1.1 版本 开始,该方法已被高效实现并集成到库中。
Xiang 等人 [XZD+23] 提出并在 OpenFHE 中实现了一种基于 NTRU 问题 的累加器加密系统(不同于 DM 和 CGGI 方案所采用的带错误学习(Learning With Errors,LWE) 的方法)。实验表明,该方法比 CGGI 方案快 2 倍以上,且更节省内存。不过,截至 OpenFHE v1.1 版本,该方法尚未正式集成到 OpenFHE 的官方发布版中。
3. CKKS 方案中的自举
Cheon-Kim-Kim-Song (CKKS) 方案是一种最新的全同态加密方案,专为浮点计算(floating-point computations) 设计 [CKKS17],在机器学习任务(如逻辑回归训练或神经网络推理)中表现最佳。
与其他 FHE 方案不同,CKKS 采用近似计算(approximate computing),并常使用多项式逼近(polynomial approximations) 来实现非线性函数(如逻辑回归函数、ReLU 激活函数等)。由于 CKKS 是近似计算的,因此其自举过程也是近似的,即自举后密文中的加密消息与自举前的消息非常接近,但不完全相等。
3.1 CKKS 方案的自举原理
CKKS 的自举方法遵循 Gentry 的自举蓝图,解密过程涉及:
- 线性函数计算(密文与私钥的内积)。
- 模约化(modular reduction)(概念上等同于四舍五入)。
具体过程如下 [CHK+18]:
- 1)第一步:隐式评估线性函数(密文与私钥的内积),通过增加密文模数(ciphertext modulus) 来实现。更大的模数允许更多的同态计算,但在自举前会引入一定的 “垃圾噪声”。
- 2)第二步:执行模约化(modular reduction) 以移除这些垃圾噪声。这一步需要使用高阶多项式插值,是整个自举过程中最昂贵的计算步骤。
此外,还涉及一些额外的计算步骤,但为简化讨论,这里省略不提。
3.2 CKKS 与 DM/CGGI 方案的主要区别
CKKS 与 DM/CGGI 方案的主要区别有:
- 1)密文数据的存储方式不同:
- DM/CGGI:每个密文仅存储一个加密标量(scalar)。
- CKKS:每个密文存储一个实数向量(vector of real numbers),其大小通常在数千级别。
这种向量编码(vector encoding) 类似于并行计算模式中的单指令多数据(Single-Instruction-Multiple-Data,SIMD) 概念:- 通过一次密文乘法,CKKS 可以同时执行数千个实数乘法。
- DM/CGGI 只能一次性自举一个数,而 CKKS 可以一次性自举成千上万个数(通常 32K - 64K)。
- CKKS 的自举延迟(latency)通常比 DM/CGGI 高,但由于 SIMD 效应,其吞吐量(throughput)远高于 DM/CGGI。
- 2)支持的精度不同:
- CKKS 方案:支持高精度计算,可高效处理单精度(23 位)或双精度(52 位)浮点数。
- DM/CGGI 方案:通常仅支持3-8 位精度。
- DM/CGGI 扩展到更高精度的效率较低,仅在某些特殊的非线性函数(如比较运算)上较为高效 [LMP22]。
- 3)可编程自举(Programmable Bootstrapping)
- DM/CGGI:原生支持可编程自举,即可以在自举过程中计算任意函数。
- CKKS:不支持可编程自举,但提供了一种高效的多项式计算机制,可用于逼近非线性函数,特别适用于平滑函数。
- 因此,在 CKKS 方案中,可以通过先执行多项式逼近,再进行自举操作,从而实现类似的功能。
在比较 DM/CGGI 和 CKKS 方案的可编程自举性能时,会始终考虑这些差异。
虽然 CKKS 的自举是近似的,但最近的研究 [BCC+22] 提出了一种优雅的优化方法,可以使自举误差几乎完全忽略不计:
- 第一次自举:对原始消息进行自举。
- 第二次自举:对第一次自举产生的first-order 一阶误差进行自举。
- 第三次自举:对** second-order 二阶误差**进行自举,依此类推。
3.3 CKKS 与 DM/CGGI 方案小结
CKKS 与 DM/CGGI 方案小结:
方案 | 自举方式 | 计算单位 | 支持精度 | 计算效率 | 可编程自举 |
---|---|---|---|---|---|
DM(FHEW)/ CGGI(TFHE) | 精确自举 | 加密单个标量 | 3-8 位 | 低延迟(单次自举快) | ✅ 原生支持 |
CKKS | 近似自举 | 加密实数向量(SIMD) | 单/双精度浮点数 | 高吞吐量(支持大规模并行计算) | ❌ 不支持,但可用多项式逼近 |
其中:
- DM/CGGI 适用于:
- 低延迟计算(布尔电路、逻辑计算)。
- 需要直接支持可编程自举的场景。
- CKKS 适用于:
- 机器学习、神经网络 等浮点数计算密集型应用。
- 需要高吞吐量计算的场景(如大规模数据处理)。
4. BFV/BGV 方案中的自举
Brakerski-Gentry-Vaikuntanathan (BGV)、Brakerski/Fan-Vercauteren (BFV) 和 CKKS 方案通常被归类为支持 SIMD(单指令多数据)的全同态加密(FHE)方案家族 [ABBB+22]。
- CKKS 方案 适用于近似计算,可处理浮点数(如机器学习应用)。
- BFV/BGV 方案 适用于精确计算,可处理整数数据类型(如数据库和字符串操作应用)。
尽管这三种方案的总体框架相似,自举策略也相同,但BGV/BFV 和 CKKS 方案的自举过程在“垃圾噪声的添加和去除”方式上存在关键差异。
在 BGV/BFV 方案 中:
- 1)垃圾噪声(garbage)被添加到一个临时扩展的明文空间。
- 2)使用数字提取多项式(digit extraction polynomials) 清除明文空间中新生成的数字的噪声,同时适当缩小消息的规模 [HS21]。
BGV/BFV 方案中的性能瓶颈在于:
- BGV/BFV 方案中的数字提取(digit extraction) 需要进行高阶多项式的同态计算,这是自举的主要计算瓶颈。
- 此外,BGV/BFV 方案采用特殊的更大明文空间,对明文代数(plaintext algebra)施加了额外限制,使得SIMD 编码的向量大小通常受限于 2K 或更小。
- BGV/BFV 吞吐量远小于 CKKS(后者支持 32K - 64K 大小的向量)。
注意BGV/BFV 方案支持两个额外的自举操作:[CGBH+18]:
- 1)缩放(scaling down)
- 2)符号计算(sign evaluation,比较运算)
BGV/BFV 方案支持有限的可编程自举,但其灵活性不如 DM/CGGI 方案。
4.1 小结
尽管 CKKS 方案的自举是近似的,但随着误差优化技术的发展,其在高精度计算中的应用潜力不断提升。
方案 | 适用计算类型 | 计算单位 | 槽位数量 | 计算精度 | 自举延迟 | 吞吐量 | 可编程自举 |
---|---|---|---|---|---|---|---|
CGGI(TFHE) | 精确计算(布尔逻辑) | 单个整数/标量 | 1 | 低(3-8 位) | ✅ 最低 | ❌ 低 | ✅ 原生支持 |
BGV | 精确计算(整数运算) | 向量(≤2K) | 2K 以下 | 中(16-32 位) | ❌ 较高 | ❌ 低 | ⚠️ 部分支持 |
CKKS | 近似计算(浮点数) | 向量(32K-64K) | 32K-64K | 高(23-52 位) | ❌ 高 | ✅ 最高 | ❌ 不支持 |
其中:
-
CGGI 适用于:
- 低延迟计算(布尔电路、逻辑计算)。
- 需要直接支持可编程自举的场景。
-
BGV 适用于:
- 精确整数计算,如数据库查询或加密搜索。
- 需要比 CGGI 更高精度但仍在整数域内的计算。
-
CKKS 适用于:
- 机器学习、神经网络等浮点计算场景。
- 大规模数据处理(高吞吐量计算)。
尽管 BGV/BFV 方案 在某些整数计算场景下优于 CGGI,但总体而言,CKKS 方案的吞吐量更高,计算效率更优,适用于大规模并行计算任务。
5. 实验设置
本文对 CGGI、CKKS 和 BGV 方案的自举性能 进行了评测。在选择方案时:
- 选取 CGGI 而非 DM 方案,因为在均匀三进制秘密分布的典型安全设置下,CGGI 方案比 DM 略快。
- BGV 和 BFV 的自举复杂度非常相似,因此实验仅考虑 BGV。
5.1 实验环境
- 计算平台:
- 处理器:Intel® Core™ i7-9700 CPU @ 3.00GHz
- 内存:64GB RAM
- 操作系统:Ubuntu 20.04.5 LTS
- 编译环境:
- 编译器:Clang 12.0.0-3ubuntu1
- OpenFHE 编译选项:
- CGGI(单比特明文空间):
NATIVE_SIZE=32
- CGGI(多比特明文空间)和 CKKS:
NATIVE_SIZE=64
- 开启机器优化:
WITH_NATIVEOPT=ON
- CGGI(单比特明文空间):
- 实验条件:
- 采用 单线程 运行(通过
OMP_NUM_THREADS=1
或WITH_OPENMP=OFF
关闭 OpenMP,确保无多线程优化)。 - 未使用 AVX-512 向量优化。
- 采用 单线程 运行(通过
- 实验的公平性
- CGGI 和 CKKS 方案均使用 OpenFHE 的相同数学库,避免了因实现差异导致的偏差,确保了 “同等比较”(apple-to-apple comparison)。
- BGV 方案的实验数据取自 [HS21]。
- 安全参数设置:所有方案均对应128 位安全级别。
5.2 性能评估
为了公平比较 CGGI(非 SIMD)、CKKS(SIMD)和 BGV(SIMD)方案的自举性能,本文统计了以下指标:
- 槽位数量(size of vector encoded in a single ciphertext 单个密文中所编码的向量尺寸)
- 比特数或精度(bits/precision)
- 延迟(latency)
- 吞吐量(throughput)
此外,对于 CKKS 和 BGV 方案,预留了大约 10 个乘法层级(multiplicative levels),以支持自举调用之间的非线性函数评估,模拟 CGGI 方案中的可编程自举。
上表为:CGGI(单/多比特明文空间)、CKKS(全填充/稀疏填充密文)和 BGV 方案的自举性能对比,其中:
- CGGI 和 CKKS 方案:使用 OpenFHE v1.1.1 进行实验。
- BGV 方案:实验数据来自 HElib。
- 所有实验 均在单线程模式下进行,未使用 AVX-512 硬件加速。
如上表所示,主要实验结论为:
- 1)CGGI 方案的自举延迟最低(单次自举最快)。
- 2)当槽位数较少、计算精度较低时,CGGI 方案最优。
- 3)当槽位数增加时,CKKS 方案最优(吞吐量更高、精度更高)。
- 4)BGV 方案的吞吐量在布尔运算(Boolean arithmetic)方面接近 CGGI,但在较大的明文空间(即高精度计算)中优于 CGGI。
- 5)CKKS 方案不需要频繁自举:
- CKKS 方案的基本运算(如乘法)通常不需要自举,仅消耗一个层级(level),并能一次同时处理数千个实数。
- CGGI 方案的整数乘法成本更高,在某些情况下可能需要额外调用自举,尤其是当乘法结果不能超出当前明文模数时。
总体而言,CKKS 方案在许多实际应用中需要的自举次数远少于 CGGI 方案,从而提供了更高的计算效率。
5.3 并行化与硬件加速说明
本文有意选择单线程 CPU 环境,以确保在相同实现下公平比较不同自举方法的性能。然而,在实际应用中,以下方法可以显著减少自举运行时间(甚至达到数量级级别的加速):
- 1)在多核/多插槽 CPU 系统上使用多线程并行计算。
- 2)利用硬件加速(如 GPU等)。
这些优化手段适用于所有自举方法,并已经在某些研究中得到了显著的加速效果。如:
- cuFHE 在 CGGI 方案 上通过 GPU 并行执行多个逻辑门,实现了 26 倍加速 [DS15]。
- [JKA+21] 研究表明,CKKS 方案的自举 通过硬件加速可实现 100 倍加速。
然而,硬件加速版本的自举实现超出了本文的讨论范围。
6. 建议与结论
本研究的目标是阐述不同的自举方法,并提供可用于实际应用的指南。主要结论如下:
- 1)CKKS 方案自举适用于:
- 密文包含大量槽位(>100),且
- 需要较高计算精度(>3-8 bit)。
- 2)DM/CGGI 方案自举适用于:
- 密文槽位较少(≤100),且
- 计算精度需求较低(≤3-8 bit)。
- 3) 可编程方式:
- DM/CGGI 方案 可通过查找表(LUT)高效计算任意函数(小整数域)。
- CKKS 方案 适用于平滑函数(如实数域),可使用多项式逼近(如 Chebyshev 插值)。
- 4)BGV/BFV 方案 的自举比 DM/CGGI 快(按槽位均摊时间计算),但比 CKKS 慢,且不支持原生任意函数计算。
- 5)硬件加速前景:
- 所有方案都可以应用硬件加速,已有研究表明加速幅度相似。
某些应用同时需要大规模数据计算(适用于 CKKS),又需要支持任意函数计算(适用于 CGGI),如决策树训练。
- 在此情况下,CKKS ↔ CGGI 方案切换(scheme switching) 可能是最佳策略。
- OpenFHE v1.1.1 已新增 CKKS 与 CGGI 之间的方案切换功能,可进一步提升应用灵活性。
如需进一步讨论本文内容,请访问 OpenFHE Discourse 论坛。
参考资料
[1] Duality团队2023年8月论文《Demystifying Bootstrapping in Fully Homomorphic Encryption》