3.4 CKKS:为浮点与机器学习而生的近似同态


3.4 CKKS:为浮点与机器学习而生的近似同态

本节摘要:CKKS 方案(二零一七年)用定点数思想处理浮点负载:明文向量乘上缩放因子后编码进多项式,乘法后通过重缩放把尺度拉回、同时消耗一档模数链。它以可控的近似误差换取对机器学习负载的天然适配,成为隐私推理与加密训练的主力编码。本节讲清编码、重缩放与精度账本,给出可套用的调用骨架与精度管理守则,并回顾二零二零年的解密攻击事件及其修复。

问题:整数世界装不下梯度

BFV 的明文是对小模数取余的整数,干净、精确,但真实负载很少长这样。神经网络的权重与激活是浮点数,取值横跨多个量级;梯度更新常常是零点零零几的小数;若把这些数硬塞进整数模数(例如放大一百万倍再编码),一次乘法后放大倍数变成一百万的平方,两三层就撞上模数天花板。放大、溢出、再放大的循环没有任何灵活性,问题出在编码模型本身。

CKKS 的回答是干脆承认"密文里算的是近似值"。它借用定点数与复数编码:把一组实数(或复数)乘上缩放因子(通常取二的四十次方量级),映射到多项式环里;密文乘法后,两数的缩放因子相乘(尺度变成二的八十次方),此时执行"重缩放"——把密文除以缩放因子、模数链同时下降一档——尺度回到二的四十次方,一切如初。重缩放在功能上正是第三章第一节模交换的亲戚:都是"除以一个数、链上掉一档",只是这里除掉的数恰好是缩放因子,所以既管理了噪声又管理了尺度,一石二鸟。

代价写在方案的名字里:近似。每次乘法与重缩放都会引入一点舍入误差,误差量级约为当前缩放因子的倒数——缩放因子取二的四十次方,单次运算的相对误差约二的负四十次方(约九亿分之一)。对求和、矩阵乘这类运算,误差线性累积;对深度电路,误差随层数温和增长。机器学习负载对此几乎无感——训练本身就在随机性与截断里泡着——这是 CKKS 与机器学习一拍即合的根本原因。

调用骨架与精度账本

# CKKS 加密浮点向量运算的调用骨架(接口形态参考主流 Python 封装库) import tenseal as ts ctx = ts.context( ts.SCHEME_TYPE.CKKS, poly_modulus_degree=8192, coeff_mod_bit_sizes=[60, 40, 40, 60], # 模数链:总二百比特,中间两档各四十比特 ) ctx.generate_galois_keys() # 旋转密钥:跨槽运算需要 sk = ctx.secret_key() vec = [0.1, 0.2, 0.3, 0.4] ct = ts.ckks_vector(ctx, vec) # 缩放因子默认约二的四十次方 ct_squared = ct * ct # 尺度升至二的八十次方 ct_poly = ct_squared * ct_squared + ct # 组合多项式:先乘后加 result = ct_poly.decrypt(sk) # 近似解密 print(result) # 约等于 [0.0101, 0.0416, 0.0981, 0.1856] # 与明文计算 x 的四次方加 x 的平方对照,前几位有效数字一致,误差在缩放因子的倒数以下

骨架里最值得注意的一行是模数链的设定:一串比特宽度列表就是模数链的形状,首尾六十比特是安全所需的"端部",中间每档四十比特支撑一次乘法(含重缩放)。链长决定了不做自举时的最大乘法深度——上面这条链撑两次乘法;隐私推理的典型配置(八千一百九十二维度、二百一十八比特总模数)能撑四到五层,再多就需要自举或换更大维度。

精度账本要记三条。第一条:有效位数约等于缩放因子的比特数减去运算消耗,四十比特缩放经五六层运算后通常剩十到十五位十进制有效数字——对推理绰绰有余,对训练要盯紧。第二条:加法不消耗模数链(不重缩放),但会累积误差;纯线性负载可以把链用得很省。第三条:跨槽运算(旋转、共轭)每次消耗少量精度并需要伽罗瓦密钥,矩阵向量乘的对角线方法要做满槽次数的旋转——这是第五章推理算例里性能的真正大头。

图:重缩放的模数链消耗

图:重缩放的模数链消耗

一场真实的安全事件

近似性除了精度账,还带来过一个真实的安全教训,值得完整讲述。二零二零年,研究人员指出 CKKS 的解密接口存在被误用的可能:CKKS 解密输出的本来就是"近似明文",如果应用把解密结果当预言机反馈使用(例如把解密输出再喂回加密流程),攻击者可以构造自适应查询,从舍入行为里反推出私钥信息。问题不在加密本身,而在"近似解密"这个接口的语义没有纳入传统安全模型。

修复路径是双管齐下的:技术上,解密前加一步"噪声泛洪"——在解密结果上叠加一个远大于舍入误差的平滑随机量,把信息通道淹没;定义上,社区提出了强化版的语义安全(在解密结果可被继续使用的意义下仍安全),并把它写进后续标准草案。这件事对工程者的教训有两层:其一,选 CKKS 就要连带选"加固的解密实现",老版本库存在隐患;其二,同态方案的安全性质要连着"你怎么用它"一起审计,接口语义本身就是攻击面。第六章讲标准化时会看到,这一事件直接影响了安全标准的措辞。

与家族的接口

CKKS 继承 BGV 的模数链与密钥交换机制(所以叫它"近似版的分层家族"),但编码、重缩放、旋转三件套都是自己的。选型上它与 BFV 划江而治:金额、计数、哈希值这类"必须逐位精确"的负载用 BFV;权重、激活、统计量这类"本来就有噪声"的负载用 CKKS。两者还能在同一个系统里协作——隐私求交的匹配阶段用整数精确比对,后续的统计阶段用浮点近似——第五章的算例会演示这种混搭。

⚠️ 常见坑:两个缩放因子不同的密文直接相加,尺度小的那个会被尺度大的淹没,有效精度骤降。实现层要么统一所有密文的尺度,要么做尺度对齐操作;日志里密文尺度不一致是排查精度异常的第一站。

  • 要点一:CKKS 用缩放因子编码浮点,乘法后重缩放归位尺度并同时消耗一档模数链,一举管理尺度与噪声
  • 要点二:精度账三条——有效位数随层数温和衰减、加法不耗链、跨槽运算是精度与性能双重大头
  • 要点三:二零二零年的解密误用攻击说明近似接口本身是攻击面,修复靠噪声泛洪与强化安全定义
  • 要点四:选型铁律是数值形态——逐位精确走 BFV,容噪负载走 CKKS,混合负载可在系统内混搭

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U