CKKS 中 规范嵌入(Canonical Embedding) 与 逆规范嵌入(Inverse Canonical Embedding) 机制
一、 核心痛点:为什么需要规范嵌入?
在同态加密(基于 Ring-LWE 假设)的世界里,存在一个严峻的“数据格式不兼容”问题:
-
密码学世界的语言是多项式: CKKS 所有的加密、解密和同态运算,都必须在一个被称为“分圆环(Cyclotomic Ring)”的特定数学结构中进行:
Rq=Zq[X]/(XN+1)
这意味着,底层密码机只能处理形如 m(x)=c0+c1x+c2x2+⋯+cN−1xN−1 的多项式(阶数为 N,系数对 q 取模)。
-
现实世界的数据是向量: 在机器学习或统计分析中,我们要处理的数据是一维数组(向量),比如由浮点数组成的 z=[z1,z2,…,zk]T。
规范嵌入的作用,就是作为“完美翻译官”,把数据向量 z 打包编码进一个多项式 m(x) 的系数中,并在计算完成后再把结果解码还原出来。 并且,它利用了多项式环的代数同构特性,赋予了同态加密强大的 SIMD(单指令多数据流) 并行计算能力。
二、 数学基石:特殊的“取值点”(单位根)
为了在多项式和向量之间建立映射,我们需要确定一组“锚点”。
因为多项式所在的环是对 XN+1 取模的,所以我们寻找方程 XN+1=0 在复数域 C 上的所有根。
根据欧拉公式,这 N 个根被称为分圆根(Roots of Unity),记为 ζ1,ζ2,…,ζN。
它们的数学表达式为(假设 M=2N):
ζk=eNi⋅(2k−1)π
核心性质: 这 N 个根在复平面上均匀分布在单位圆上,并且它们天然是成对的共轭复数。也就是说,如果存在一个根 ζ,必定存在另一个根 ζˉ。
三、 完整过程:数学推导与矩阵公式
数据在 CKKS 中的流动,首先经历**逆规范嵌入(编码)进入密文世界,计算完成后,再经历规范嵌入(解码)**回到现实世界。
1. 编码过程:逆规范嵌入 (σ−1) —— 从向量求多项式
这是 CKKS 数据输入时(加密前)真正执行的操作。
我们的目标是:给定一个已知的数据向量 z=[z1,z2,…,zN]T,求出一个未知的多项式 m(x)=c0+c1x+⋯+cN−1xN−1。
满足的条件是:当把单位根 ζi 代入 m(x) 时,计算结果恰好等于向量中的元素 zi。
步骤 A:构建并求解线性方程组
将 N 个根代入多项式,我们得到 N 个方程:
m(ζk)=c0+c1ζk+c2ζk2+⋯+cN−1ζkN−1=zk(对 k=1,…,N)
将这组方程写成极其优雅的矩阵乘法形式:
V (范德蒙德矩阵)11⋮1ζ1ζ2⋮ζNζ12ζ22⋮ζN2……⋱…ζ1N−1ζ2N−1⋮ζNN−1×c (未知的多项式系数)c0c1⋮cN−1=z (你的业务数据)z1z2⋮zN
左侧由单位根组成的矩阵被称为 范德蒙德矩阵 (Vandermonde Matrix,记作 V)。
因为所有根 ζk 互不相同,矩阵 V 是可逆的。我们只需两边左乘逆矩阵,即可求出多项式系数:c=V−1×z
步骤 B:满足“实数系数约束”(为何只能打包 N/2 个数据?)
密码学 LWE 算法有一个物理限制:多项式 m(x) 的系数 cj 必须全都是实数(R)。
这里引入一个基础代数定理:实系数多项式对于共轭复数输入,必然产生共轭复数输出。
证明如下:
m(ζˉ)=∑j=0N−1cj(ζˉ)j=∑j=0N−1cjζj=∑j=0N−1cjζj=m(ζ)
还记得前面说的吗?我们的取值点 ζ 都是成对的共轭复数。如果我们在根 ζ1 处强行塞入数据 z1,那么在它的共轭根 ζˉ1 处,输出的结果身不由己地变成了 zˉ1(z1 的复数共轭)。
- 工程限制: 你的目标向量 z 不能完全乱填。它的前 N/2 个槽位可以填你真实的业务数据;但后 N/2 个槽位,必须严格填入前一半数据的共轭镜像!
- 结论: 一个最高次幂为 N−1 的多项式,至多只能独立打包 N/2 个数据。
步骤 C:使用 FFT 加速运算(工程奇迹)
如果直接计算 V−1×z,矩阵乘法的复杂度是 O(N2)。当 N=32768 时,这种计算慢如蜗牛。
但是,因为 V 的元素是呈周期性分布的分圆根,这个特定的矩阵求逆运算,在数学上等价于对向量做一次 逆离散傅里叶变换(IDFT)。
通过使用 逆快速傅里叶变换(IFFT)算法,计算复杂度瞬间从 O(N2) 降到了 O(Nlog2N),让原本需要几分钟的编码过程在毫秒级内完成。
2. 解码过程:正向规范嵌入 (σ) —— 从多项式求向量
这是 CKKS 数据输出时(解密后)执行的操作。
当你在密文状态下完成了机器学习预测,解密后得到了一个结果多项式 mres(x)。此时你只需顺向执行一遍操作,把数据提取出来。
根据规范嵌入的定义,就是将 N 个单位根代入多项式求值:
σ(mres)=(mres(ζ1),mres(ζ2),…,mres(ζN))
写成矩阵形式,就是计算正向的范德蒙德乘法:
zres=V×cres
同理,工程上这等价于做一次 离散傅里叶变换(DFT),使用 FFT 算法极速提取出前 N/2 个元素,就是你的最终预测结果。
四、 终极魔法:SIMD 与环同构的代数证明
费这么大劲折腾矩阵和多项式,根本原因是它能带来 SIMD(单指令多数据流),即“算一次多项式乘法,等于同时算几千次浮点数乘法”。
下面是用代数理论对这一奇迹的严格证明。
假设多项式 A(x) 和 B(x) 分别编码了向量 a 和 b。(A(ζ)=a和B(ζ)=b)
加法并行:
C(x)=A(x)+B(x)
代入 ζk: C(ζk)=A(ζk)+B(ζk)=ak+bk。 (向量按位独立相加)
乘法并行(最精妙之处):
在密码学环中,多项式相乘必须对 XN+1 取模:
C(x)=A(x)⋅B(x)(modXN+1)
根据多项式带余除法定理,必定存在一个商多项式 Q(x) 使得:
A(x)⋅B(x)=Q(x)(XN+1)+C(x)
现在,我们把单位根 ζk 代入这个等式左右两边:
A(ζk)⋅B(ζk)=Q(ζk)(ζkN+1)+C(ζk)
见证奇迹的时刻: 因为 ζk 是方程 XN+1=0 的根,所以 ζkN+1=0 永远成立!
中间那一坨复杂的 Q(ζk)(ζkN+1) 直接灰飞烟灭,变成了 0。
等式瞬间化简为:
C(ζk)=A(ζk)⋅B(ζk)=ak⋅bk
证明完毕:两个长达 N 维的多项式在环内执行 1 次取模乘法,其效果在规范嵌入下,完美的等价于背后 N/2 个独立数据进行了并行的按位乘法!
五、 CKKS 规范嵌入完整生命周期总结
我们梳理出数据在 CKKS 中的一生:
- 准备与镜像: 提取 N/2 个真实业务浮点数,求其复数共轭补充到后 N/2 个位置,拼成长度为 N 的向量 z。
- 编码 (σ−1): 求解 c=V−1z(工程上通过 IFFT 加速),将向量转化为拥有实数系数的未加密多项式 m(x)。
- 缩放取整: 将实数系数 ci 乘以巨大的 Scale 因子 Δ(如 240)并四舍五入,变成符合密码学要求的整数多项式。
- 加密与密态计算: 送入 LWE 密码机加密,利用上述证明的 SIMD 同构特性,在密文状态下只需执行 1 次多项式运算,即完成成千上万条数据的批量计算。
- 解密与重缩放: 密钥解密还原出结果多项式,除以 Δ 恢复原本的精度级别。
- 解码 (σ): 求解 zres=Vcres(工程上通过 FFT 加速),将单位根代入多项式,顺利提取出最终的业务计算结果。
六、计算案例
在处理 Transformer 或大语言模型(LLM)时,输入的数据通常是多个 Token,且每个 Token 都有一个多维的 Embedding(特征向量)。
如果在现实工程中,你要加密处理 2 个 Token,且每个 Token 的 Embedding 是 2 维的,同态加密工程师会使用一个极其巧妙的行业标准优化技巧:复数打包(Complex Packing)。
6.1 行业技巧:如何把 2D 向量塞进 CKKS?
在上一节我们讲过,CKKS 因为复数共轭的限制,最多只能提供 N/2 个数据槽位。
如果采用“平铺打包”(把数字排成一排),我们需要 4 个槽位来放这 4 个数字。
但由于 CKKS 天然原生支持复数运算,业界更聪明的做法是:将一个 2D 特征向量 [x,y],直接映射为一个复数 x+yi!
- Token 1 的特征 为 [1.0,2.0] ⟹ 编码为复数 z1=1.0+2.0i
- Token 2 的特征 为 [3.0,4.0] ⟹ 编码为复数 z2=3.0+4.0i
这样做的好处是绝大的: 2 个 Token,无论特征维度如何,只需要占用 2 个复数槽位!所以我们依然可以使用极小的迷你多项式环(N=4,容量为 2)。
业务目标:
我们要在密文下,给 Token 1 的特征乘以注意力权重 2.0,给 Token 2 乘以权重 3.0。
- 期望结果:Token 1 变成 [2.0,4.0];Token 2 变成 [9.0,12.0]。
下面是见证魔法的详细推导。
(参数设定:N=4,模数 X4+1,取值点 r1=0.707+0.707i,r2=−0.707+0.707i,缩放因子 Δ=100)
6.2 第一步:准备数据与镜像 (Data Preparation)
-
输入向量 A(Token特征): z1=1+2i, z2=3+4i。
为了满足多项式系数是实数的物理定律,向量后半段必须是前半段的共轭:
完整向量:zToken=[1+2i,3+4i,3−4i,1−2i]T
-
输入向量 B(Attention权重): 我们要把权重也写成复数(虚部为0)。
完整向量:zWeight=[2+0i,3+0i,3−0i,2−0i]T
6.3 第二步:逆规范嵌入 (编码为多项式)
计算机底层快速解范德蒙德方程组,寻找多项式 M(x)=c0+c1x+c2x2+c3x3。
这里我为你手工解出了精确的解析解(代入上述 r1,r2 等根):
1. Token 特征多项式 MA(x)
计算得出:
MA(x)=2.0+1.414x−1.0x2+2.828x3
(把 r1=0.707+0.707i 代入这个实数多项式,结果等于 1.0+2.0i!这也证明了实系数多项式能生成复数!)
2. 权重多项式 MW(x)
计算得出:
MW(x)=2.5−0.3535x+0x2+0.3535x3
6.4 第三步:缩放与取整 (变身密码学数据)
乘以 Δ=100 并去掉小数,变成可被加密的纯整数多项式:
-
MA′(x)=200+141x−100x2+283x3
-
MW′(x)=250−35x+0x2+35x3
随后,系统将它们加上噪声,加密成谁也看不懂的密文。
6.5 第四步:密文并行计算 (SIMD 乘法爆发)
在完全加密的状态下,计算机直接将这两个乱码多项式相乘。底层等价于发生以下运算:
C(x)=MA′(x)×MW′(x)(modX4+1)
1. 暴力展开相乘(产生 16 个项并合并):
- 常数项: 200×250=50000
- x 项: (200×−35)+(141×250)=−7000+35250=28250x
- x2 项: (141×−35)+(−100×250)=−4935−25000=−29935x2
- x3 项: 200×35+(−100×−35)+283×250=7000+3500+70750=81250x3
- x4 项: (141×35)+(283×−35)=4935−9905=−4970x4
- x5 项: (−100×35)=−3500x5
- x6 项: (283×35)=9905x6
2. 模 X4+1 代数消元(降维打击):
因为密码学规定 x4+1=0,所以 x4=−1, x5=−x, x6=−x2。代入化简超高次项:
- −4970x4⇒+4970 (并入常数项)
- −3500x5⇒+3500x (并入 x 项)
- 9905x6⇒−9905x2 (并入 x2 项)
3. 最终结果多项式:
- 常数:50000+4970=54970
- x 项:28250+3500=31750x
- x2 项:−29935−9905=−39840x2
- x3 项:81250x3
得出的密文计算结果: MRes′(x)=54970+31750x−39840x2+81250x3
6.6 第五步:解密与重缩放
我们拿私钥解开密文,得到上面的结果。此时因为经历了乘法,Scale 膨胀成了 100×100=10000。
将所有系数除以 10000 恢复浮点数:
MFinal(x)=5.497+3.175x−3.984x2+8.125x3
6.7 第六步:正向规范嵌入 (解码提取 Embedding)
最激动人心的时刻到了。刚才我们只是将两个多项式做了一次纯粹的代数相乘,现在我们来看看,把单位根代进去,能提取出那两个 Token 的 2D 特征吗?
提取 Token 1 结果(代入 r1=0.707+0.707i):
(注意:r12≈i, r13≈−0.707+0.707i)
MFinal(r1)=5.497+3.175(0.707+0.707i)−3.984(i)+8.125(−0.707+0.707i)
- 实部 (Token 1 的维度1): 5.497+2.244−5.744=1.997≈ 2.0
- 虚部 (Token 1 的维度2): 2.244i−3.984i+5.744i=4.004i≈ 4.0
⟹ 结果解码为 [2.0,4.0]。完全匹配业务预期 ([1.0,2.0]×2.0)!
提取 Token 2 结果(代入 r2=−0.707+0.707i):
(注意:r22≈−i, r23≈0.707+0.707i)
MFinal(r2)=5.497+3.175(−0.707+0.707i)−3.984(−i)+8.125(0.707+0.707i)
- 实部 (Token 2 的维度1): 5.497−2.244+5.744=8.997≈ 9.0
- 虚部 (Token 2 的维度2): 2.244i+3.984i+5.744i=11.972i≈ 12.0
⟹ 结果解码为 [9.0,12.0]。完全匹配业务预期 ([3.0,4.0]×3.0)!
(注:出现 1.997 和 4.004 的微小误差,正是因为我们在第三步使用了极小的 Scale Δ=100。在真实的 CKKS 中,Δ 通常是 240,算出来的结果会是 2.000000001,完美等价于浮点数精度。)