3. 同态加密算法概览:BGV、BFV、CKKS、TFHE 的原理对比与适用场景

咱们做日志聚合查询,说白了就是在密文上做计算。但同态加密不是一门统一的法术,它分好几条路。每条路的设计哲学、数学基础、适用场景都不太一样。如果你选错了方案,性能会差一个数量级,甚至功能都跑不通。

我个人习惯,在决定用哪个方案之前,先搞清楚这几件事:你要算整数还是实数?电路深度大不大?容忍多少性能损耗?想清楚这些,再选算法。

这一章,咱们把目前最主流的四个方案——BGV、BFV、CKKS、TFHE,挨个拆解一遍。我会结合我在日志系统中的踩坑经验,给你讲清楚:它们各自长什么样,有什么短板,以及什么时候该用谁。

3.1 BGV 方案

BGV 是 Brakerski-Gentry-Vaikuntanathan 的缩写,2011年提出。它是最早进入实用化阶段的层次型全同态方案之一。

BGV 的核心思路是模数切换(Modulus Switching)。你可以理解为:每次乘法都会让噪声膨胀,BGV 通过减小密文模数把噪声压下来。代价是模数会一步步变小,最终算到极限就停了。所以 BGV 天然适合已知深度的电路。

关键特性:BGV 的密文可以看作“多项式环上的向量”。它支持在同一个密文里打包多个消息(SIMD 技术),这对批处理非常友好。

我在项目中遇到过一个问题:如果用 BGV 做日志平均值的聚合,需要预先知道日志记录的总条数,否则模数链长度定不下来。你想想看,如果日志流是无限的,BGV 就有点尴尬。

3.2 BFV 方案

BFV(Brakerski-Fan-Vercauteren)与 BGV 几乎同时期。它俩解决的是同一个问题,但路子不一样。

BFV 用的是缩放因子(Scaling Factor)。它把明文放大后再塞进密文,计算完再缩放回来。噪声控制靠的是“relinearization”和“rescaling”的组合拳。

对比维度 BGV BFV
噪声管理方式 模数切换(变小) 缩放因子(动态调整)
密文膨胀 较低 中等
乘法性能 稍快 加解密稍慢
整数精度 精确 精确
避坑指南:我曾经在两个方案之间纠结了很久。后来发现,如果日志字段是固定长度的整数(比如时间戳),BFV 的编程模型更直观。如果字段是大量短整数的向量,BGV 的 SIMD 优势更大。

3.3 CKKS 方案

CKKS(Cheon-Kim-Kim-Song)2017年才提出。它一出世,咱们工程师的眼睛就亮了——因为它支持近似计算。

日志聚合里,平均值、方差、百分位数……这些统计量通常都涉及实数运算。BGV 和 BFV 做实数要自己编码,很麻烦。CKKS 直接把实数放进去,允许计算过程中有一个可控的误差。这个误差一般在 \(10^{-5}\) 级别,对统计查询来说完全够用。

注意:CKKS 不是精确的。如果你做的是“COUNT DISTINCT”这种需要精确匹配的查询,CKKS 可能不合适。误差在小数位上积累,最终可能导致排序错误。

你想想看,日志分析里,99%的查询都不要求数学上的精确值。你要的是“今天平均延迟是 120.3ms 还是 120.5ms”?这个误差完全能接受。

我个人偏好,在日志聚合场景里,CKKS 是最实用的选项。性能好,精度够,代码写起来也省心。

3.4 TFHE 方案

TFHE(Fast Fully Homomorphic Encryption over the Torus)2016年由 Chillotti 等人提出。它有个独门绝技:单次运算速度快,支持任意次数的自举(Bootstrapping)。

什么叫自举?就是清空噪声,让密文回到初始状态。BGV 和 BFV 也能做,但慢。TFHE 的自举只需毫秒级别。这意味着你可以做任意深度的电路,不用提前规划。

但代价是:TFHE 的单次乘法或比较操作比 BGV 慢。它适合做“控制流密集”的任务,比如密文比较、条件选择、分支判断。

  • 优势:支持任意深度计算,自举速度快,适合做查找表(LUT)。
  • 劣势:单次操作开销大,对批量向量处理不友好。
  • 适合场景:需要在密文上做条件判断(比如“如果值大于阈值则触发告警”)。
经验之谈:我在做“密文阈值告警”这个功能时,试过 BFV,发现比较操作需要转化成减法再判断符号位,电路深度直接炸了。换成 TFHE,逻辑清晰,性能反而更好。

3.5 四种方案核心对比

我把它们的核心参数放在一张表里,方便你对照。

方案 设计目标 数据类型 适用场景 性能特点 缺点
BGV 层次全同态 整数(精确) 固定深度批处理 SIMD 快,乘法低延迟 深度受限
BFV 层次全同态 整数(精确) 通用整数计算 编程模型直观 解密开销大
CKKS 层次全同态 实数(近似) 统计、ML、日志聚合 近似计算,性能好 有误差
TFHE 自举全同态 二进制/小整数 条件判断、控制流 任意深度,自举快 单次操作慢

3.6 怎么选?我的经验法则

搞清楚区别以后,选型就不难了。我一般按这个流程走:

  1. 看数据类型:是整数还是实数?整数走 BGV 或 BFV,实数直接上 CKKS。
  2. 看电路深度:如果计算步骤超过 10-20 层,而且不能提前规划,TFHE 更合适。
  3. 看批量程度:如果一次要处理百万级记录,BGV 的 SIMD 是最优解。
  4. 看精度要求:需要精确到位的匹配,不要用 CKKS。

嗯,这里要注意:写代码的时候,不要为了“通用”去封装一个万能库。同态加密跟传统加密不一样,参数配错了直接跑不动。我见过有人用 BGV 的参数去跑 CKKS 的电路,结果噪声炸了,解密全错。

最终建议:如果是做日志聚合查询,90%的场景用 CKKS 就够了。剩下的 10%(精确计数、条件过滤)可以依赖 TFHE 或 BFV 做辅助。不要试图用一个方案解决所有问题。

3.7 知识体系图

下面这张图概括了四种方案在日志聚合场景中的定位。你可以用它来做选型参考。

同态加密日志聚合 —— 算法选型思维导图 日志聚合查询 数据类型判断 整数 (精确) 实数 (近似) BGV (批处理) BFV (通用整数) CKKS (近似计算) TFHE (条件/任意深度) 虚线:TFHE 作为整数/实数场景的补充(用于条件过滤、阈值判断等控制密集型操作) 实线:主路径。数据是整数选 BGV/BFV,数据是实数选 CKKS

这张图你多看几眼。实际写代码时,先定位你的数据在哪个节点,再往下走,基本不会选错。

好,这一章就到这里。算法选型是基础,基础打牢了,后面写聚合查询逻辑才能顺手。