跳到正文
Go back

阅读论文 A Full RNS Variant of Approximate Homomorphic Encryption

编辑此页

这篇论文 《A Full RNS Variant of Approximate Homomorphic Encryption》(Cheon 等,SAC 2018)解决了 CKKS/HEAAN 早期实现的一个关键工程瓶颈:如何在不依赖大整数库的前提下,让 CKKS 的核心流程完全运行在 RNS(剩余类系统)+ NTT 的字长运算上

如果你只记住一句话:它允许中间过程带着“QQ 的倍数噪声”跑,最终回到模 QQ 时这些噪声会自然消失;真正付出的代价主要是 ModDown(除法/取整)处的微小近似误差。

目录

1. 背景:原版 CKKS 为什么难以 RNS 化?

2. Full RNS 的核心改法:用“可控近似”换“字长性能”

论文提出全 RNS 变体(Full RNS Variant),核心是两点:

2.1 近似模数链(Approximate Basis)

不再强制 QQ 必须是某个缩放因子 qq 的严格幂,而是选取一组互素素数作为 RNS 基:

这会引入额外误差,但论文论证:只要参数设置得当(误差低于明文有效精度),结果仍可用。

2.2 近似模数切换(Approximate Modulus Switching)

为了让密钥切换(Key Switching)等过程能在 RNS 域完成,论文给出可在 RNS 上执行的近似:

工程上通常还会选择满足 qi1(mod2N)q_i \equiv 1 \pmod{2N} 的素数,使每个 RNS 分量上都能高效做 NTT。

3. 关键子程序:快速(近似)基变换在算什么?

在 RNS 中,一个整数/系数 XX 表示为:

X(x0,,x1),xi=XmodqiX \leftrightarrow (x_0,\dots,x_{\ell-1}),\quad x_i = X \bmod q_i

Full RNS 的目标是避免“把 RNS 重构回大整数再处理”。它使用一种快速基变换(fast basis conversion)思路,直接在字长模运算里完成“从一个基到另一个基”的映射。

设两套 RNS 基:

给定 [a]C[a]_{\mathcal{C}} 计算 [a]B[a]_{\mathcal{B}} 时,一种常见写法为:

ConvCB([a]C)=(j=01[a(j)q^j1]qjq^jmodpi)0i<k, q^j=Q/qj\mathrm{Conv}_{\mathcal{C}\to\mathcal{B}}([a]_{\mathcal{C}}) = \left( \sum_{j=0}^{\ell-1} [a^{(j)}\cdot \widehat{q}_j^{-1}]_{q_j}\cdot \widehat{q}_j \bmod p_i \right)_{0\le i<k}, \ \widehat{q}_j = Q/q_j

这一步“近似”的含义是:它对应的整数 a~\tilde a 往往满足

a~=a+Qe\tilde a = a + Q\cdot e

其中 ee 很小。虽然 QeQ\cdot e 看起来可能很大,但在模 QQ 下它是“隐形”的:

a+Qea(modQ)a + Q\cdot e \equiv a \pmod Q

这就是后面“噪声消失”的关键伏笔。

4. 主戏:密钥切换里,为什么 QeQ\cdot e 不会把结果毁掉?

密钥切换/重线性化通常需要先把模从 QQ 扩到 PQPQ,运算后再降回 QQ

4.1 近似 ModUp:从 QQ 提升到 PQPQ

cRQc\in R_Q 做近似提升得到 c~RPQ\tilde c \in R_{PQ}

c~=c+Qv\tilde c = c + Q\cdot v

其中 vv 很小,但 QvQ\cdot v 形式上可能“看起来很吓人”。

4.2 与切换密钥相乘:噪声被“绑上”了 PP

切换密钥可抽象为(省略若干细节项):

swk(as2+Ps1+E, a)(modPQ)\mathrm{swk} \approx (-a's_2 + P\cdot s_1 + E,\ a') \pmod{PQ}

内积里会出现:

Term=c~(Ps1)(modPQ)\mathrm{Term} = \tilde c\cdot (P\cdot s_1)\pmod{PQ}

代入 c~=c+Qv\tilde c=c+Q\cdot v

Term=(c+Qv)(Ps1)=cPs1信号项  +  QvPs1干扰项\begin{aligned} \mathrm{Term} &= (c+Q\cdot v)\cdot (P\cdot s_1) \\ &= \underbrace{c\cdot P\cdot s_1}_{\text{信号项}} \;+\; \underbrace{Q\cdot v\cdot P\cdot s_1}_{\text{干扰项}} \end{aligned}

干扰项同时带有因子 QQPP

4.3 近似 ModDown:除以 PP,并回到模 QQ

最后要把结果降回 RQR_Q 并“除以 PP”:

Qvs10(modQ)Q\cdot v\cdot s_1 \equiv 0 \pmod Q

因此,ModUp 阶段引入的“QQ 的倍数噪声”会在回到模 QQ 时自然归零。

5. 真正的代价:误差从哪里来?

上面消掉的是 QQ 的倍数噪声。真正的近似误差主要来自 ModDown 的除法/取整:在 RNS 域里无法像大整数那样做完全精确的除 PP,会出现

Result=X/P+esmall\mathrm{Result} = \left\lfloor X/P \right\rfloor + e_{\mathrm{small}}

其中 esmalle_{\mathrm{small}} 是很小的舍入误差。对 CKKS 来说,只要参数使该误差小于明文有效精度,这个代价通常是可接受的。

【硬核科普】全 RNS 同态加密(Part 2):Rescale 与 ModDown 的本质区别——为何看似相同的除法,实现却天差地别?

在阅读全 RNS 变体(Full RNS Variant of HEAAN/CKKS)的论文或代码时,你可能会发现一个有趣的现象:Rescale(重缩放)ModDown(模数约减) 在数学形式上惊人地相似。

它们本质上似乎都在做同一件事:

cnew=cold(cold(modM))Mc_{new} = \frac{c_{old} - (c_{old} \pmod M)}{M}

即:减去余数,然后除以模数。

然而,在工程实现中,Rescale 只是几行简单的减法和乘法,而 ModDown 却需要调用复杂的“近似基变换”算法。为什么会有这种差异?能不能用连续执行 Rescale 的方式来替代 ModDown?

本文将带你从数学原理和工程优化两个维度,彻底理清这两个操作的爱恨纠葛。

1. 灵魂拷问:目的与对象的根本不同

虽然动作都是“除法”,但两者的动机和对消息(Message)的影响截然不同。

Rescale (重缩放):为了“丢弃”

mnewmold/q(Δ2x2)/Δ=Δx2m_{new} \approx m_{old} / q_\ell \approx (\Delta^2 \cdot x^2) / \Delta = \Delta \cdot x^2

我们是故意要除去一部分数据的(即那个多出来的 Δ\Delta),以维持缩放比例恒定。

ModDown (近似模数约减):为了“还原”

mnewmold/P=(Pm)/P=mm_{new} \approx m_{old} / P = (P \cdot m) / P = m

我们不想丢失任何消息信息,只是想把“保护壳”拆掉。

2. 算法实现的鸿沟:标量 vs. 向量

为什么 Rescale 很简单,而 ModDown 很复杂?核心在于余数(Remainder)的大小以及我们在哪个基(Basis)上计算

Rescale:简单的标量广播

当我们做 Rescale 时,我们要除以 qq_\ell

ci(cir)q1(modqi)c_i \leftarrow (c_i - r) \cdot q_\ell^{-1} \pmod{q_i}

ModDown:跨越维度的向量翻译

当我们做 ModDown 时,我们要除以 PP

我们需要先把 RR 从基 B\mathcal{B} 翻译(转换)到基 C\mathcal{C},计算出 R(modqi)R \pmod{q_i} 的值。这就需要用到论文中提到的 Conv_B->C 算法。

Target=(cin_QConvertBC(cin_P))P1\text{Target} = (c_{in\_Q} - \text{Convert}_{\mathcal{B} \to \mathcal{C}}(c_{in\_P})) \cdot P^{-1}

这就是 ModDown 如此复杂的根本原因:它涉及两个不同 RNS 基之间的数据搬运。

3. 深度思考:为什么不能“连续 Rescale”?

既然 P=p0p1P = p_0 \cdot p_1 \cdots,我们能不能不像 Algorithm 2 那样一次性除以 PP,而是像剥洋葱一样,先 Rescale p0p_0,再 Rescale p1p_1……直到把 PP 里的素数都除完?

答案是:理论上可行,但工程上是“血亏”的。

这种方法称为 Sequential Rescaling(顺序重缩放),它比 ModDown(批量处理) 差在以下三点:

A. 算力的无谓浪费 (Lazy Reduction)

如果你决定先除以 p0p_0

  1. 你不仅要更新 QQ 部分的分量。
  2. 你还必须更新 p1,p2,p_1, p_2, \dots 这些 PP 部分的分量!

为什么?因为为了下一步能继续除以 p1p_1,你必须知道当前密文在 p1p_1 下的余数。而一旦你改变了密文(除以了 p0p_0),原来的余数就失效了,必须重新计算。

然而,这些 PP 分量的唯一宿命就是被丢弃。花费 O(k2)O(k^2) 的算力去维护这些“即将死亡”的模数分量,是极大的浪费。

ModDown 的做法:它在 t=0t=0 时刻一次性读取所有 PP 分量,算完直接把整个 PP 部分扔掉。它从不更新 PP 部分的数据,实现了极致的“懒惰计算”。

B. 噪声结构的破坏

全 RNS 变体依赖于 aa+Qe(modQ)a \equiv a + Q \cdot e \pmod Q 这一特性。

总结:一图胜千言

特性Rescale (重缩放)ModDown (Algo 2)
形象比喻科学计数法调整
(1.23×10212.3×1011.23 \times 10^2 \to 12.3 \times 10^1)
拆快递
(把为了运输加上的保护箱 P 拆掉)
数学除数单个小素数 qq_\ell模数积 PP (一组素数的乘积)
余数获取直接读取 (O(1)O(1))需要基变换 (O(k)O(k\ell))
对模数链降级 (不可逆)恢复 (回到计算层)
工程策略逐层剥离批量处理 (Lazy)

看懂了 Rescale 和 ModDown 的区别,你就真正看懂了 CKKS 全 RNS 优化的核心逻辑。前者是算法正确性的保证(控制 Scale),后者是工程性能的保证(快速 KeySwitch)。

(未完待续…)

【进阶思考】批量处理总是最好的吗?——来自 WAHC 2023 的反直觉启示

这里顺便澄清一下你可能在笔记/代码里看到的缩写:WAHC 指代的论文是

数学结构上看,WAHC 2023 论文中的 Composite Scaling(tt 个小素数组成一个 qq_\ell 与常规 CKKS 中的 KeySwitching 辅助模数(kk 个小素数组成 PP 是高度同构的:

它们面临的本质问题都是:如何在一个 RNS 系统中,除以一个由多个小素数组成的“大整数”?

因此,论文关于“逐步处理(Iterative)误差小于批量处理(Batch FBC)”的结论,理论上也可以迁移到 ModDown(去 PP)的讨论中——这是一个很棒的进阶/延伸知识点。

在上一节中,我们对比了 Rescale(单素数除法)ModDown(多素数批量除法),并指出 ModDown 采用了“一次性打包(Batch)”的策略来追求效率。

然而,“批量处理”在任何情况下都是最优解吗?

如果我们的硬件受到限制(例如只有 32 位字长),或者我们对精度的要求到了极致,情况会发生什么变化?

这正是 WAHC ’23 想回答的问题:它揭示了 RNS 除法中一个鲜为人知的 精度-效率权衡(Precision-Efficiency Trade-off)

1. 场景重构:当 Rescale 也变成了“多素数”问题

在 32 位嵌入式设备或 GPU 上,单一的 32 位素数不足以提供足够的精度(通常 Scaling Factor Δ240260\Delta \approx 2^{40} \sim 2^{60})。

为了解决这个问题,作者提出 Composite Scaling(组合缩放):用 tt 个小的 32 位素数乘积来模拟一个大的 Scaling Factor。

q=q,0q,1q,t1Δq_\ell = q_{\ell,0} \cdot q_{\ell,1} \cdots q_{\ell,t-1} \approx \Delta

这就导致了一个有趣的现象:现在的 Rescale 操作,数学上变得和 ModDown 一模一样了! 它们都需要除以一个由多个 RNS 分量组成的积。

2. 巅峰对决:逐步去除 vs. 一次性去除

面对这个“多素数除法”问题,作者对比了两种策略:

3. 结论与启示

惊人的结论: 在 WAHC ’23 中,作者指出**“逐步法”在理论误差控制上优于“批量法”**(误差界小了 t\sqrt{t} 倍)。

这给我们带来了什么启示?

  1. 对于 KeySwitching(ModDown)

    目前的标准库(SEAL、OpenFHE)依然使用批量法去除 PP

    • 原因PP 包含的素数数量 kk 通常不多(2~4 个),k\sqrt{k} 的误差放大往往可以接受。并且 KeySwitching 本身就是性能瓶颈,工程上更愿意用一点噪声换速度。
  2. 对于受限硬件(Composite Scaling)

    tt 变大(例如为了凑 60 bit 精度,32 位机器需要更多小素数),或者在深度神经网络等对噪音极度敏感的任务中,“逐步法” 可能成为更好的选择。

总结

此补充内容受 WAHC ’23 论文启发,特此致谢。

6. 性能结论(论文数据)

论文将 HEAAN-RNS 与早期 HEAAN 实现对比(Intel Core i5 单核):

这条路线后来也成为现代同态加密库实现 CKKS 的常见做法(如 Microsoft SEAL、OpenFHE、Lattigo 等)。

7. 小结

全 RNS 变体的工程思想可以概括为:

  1. 不再执着于中间步骤的“精确大整数重构”
  2. 允许中间结果携带 QQ 的倍数误差,并利用同余结构在回到模 QQ 时自然消失
  3. 把关键算子落到 RNS 分量的 64 位运算 + NTT 上,从而获得数量级加速

本文基于 SAC 2018 论文 “A Full RNS Variant of Approximate Homomorphic Encryption” 整理。


编辑此页
Share this post on:

Previous Post
密钥切换 - hybrid Approach
Next Post
GPU课程大作业系列