同态加密如何让私有AI在云端密文推理走向实用
2026/9/24 16:07:14 网站建设 项目流程

当业务开始把大模型推理、用户画像、个性化搜索放进云端的时候,最先被挑战的往往不是模型效果,而是“数据和隐私能不能被安全地交给服务方”。早期的做法是传输前加密、内存中隔离,再进一步是可信执行环境;但若你希望数据在服务端始终以密文状态参与推理,那么同态加密(Homomorphic Encryption, HE)就成了绕不开的技术方向。

本篇文章围绕“Google 正在让私有 AI 通过同态加密走向实用”的话题,从同态加密的基本原理、工程约束、典型 AI 场景,到可直接运行的 Python 加密推理 Demo,整理一套适合入门到工程落地的完整笔记。无论你是做后端服务、隐私计算,还是正在调研 AI 模型部署中的数据保护方案,都能按本文思路快速建立认知并动手验证。

1. 从“私有 AI 不隐私”谈起

1.1 AI 服务背后的隐私错位

现阶段的 AI 服务,尤其是云端推理,普遍采用“用户传明文 -> 服务端计算 -> 返回明文结果”的模型。用户为了得到模型能力,不得不把文本、图片、搜索词、业务数据全部暴露给服务方。这在很多场景下并不等价于用户真正知情同意,更多时候是“没有别的选择”。

更深层的矛盾来自模型本身的价值:

  • 模型权重是服务方的核心资产,不能直接交付给用户;
  • 用户输入是用户的核心隐私,不能明文上传;
  • 可预测的业务逻辑如果被批量探测,还可能形成模型窃取、数据重放等安全风险。

传统的 TLS 加密只保护了网络传输过程,服务端拿到数据后仍然能直接读取明文。解决“数据可用不可见”的关键,并不是再加一层传输加密,而是让计算本身发生在密文上。这就是同态加密被称为“隐私 AI 最终答案之一”的原因。

1.2 同态加密到底是什么

同态加密是一种允许直接在密文上执行计算的加密技术。用公式可以直观表达为:

Enc(a) ⊕ Enc(b) = Enc(a + b)

如果定义一种对应的密文运算“⊕”,那么加密后的数据经过计算再解密,得到的结果与明文上执行相同计算的结果一致。根据支持运算程度的不同,HE 可分为几个层次:

  • 部分同态加密(PHE):只支持加法或只支持乘法,例如 RSA 乘法同态、Paillier 加法同态;
  • 近似同态加密(Somewhat HE):支持一定深度的加法和乘法,但深度超过上限后噪声膨胀,结果无法正确解密;
  • 全同态加密(FHE):理论上支持任意深度的加法和乘法,代表方案有 BFV、BGV、CKKS、TFHE 等。

AI 推理本质上是大量矩阵乘法、卷积、激活函数的组合,所以能否同时支持加法和乘法,决定了该方案能否用于神经网络。这也是 Google 等团队研究“私有 AI”时聚焦全同态加密或层次同态加密的原因。

1.3 为什么一直说“不实用”

提到同态加密,很多开发者的第一反应是“性能太差,工业界用不了”。这种印象并非没有依据。

同态加密的核心瓶颈在于三个层面:

  • 密码学开销:密文尺寸通常是明文的几十到上千倍,密文乘法远比明文乘法复杂;
  • 噪声管理:每次密文乘法都会扩大噪声,必须通过重线性化(relinerization)、模数切换(modulus switching)控制噪声;
  • 算子不匹配:ReLU、Softmax、除法等 AI 常用非线性函数,很难直接拆解成有限次的加法和乘法。

因此,把 HE 从学术论文推进到 AI 工程,真正困难的不是“加密数据可计算”这个结论,而是如何让推理框架、编译器、硬件加速器和模型量化策略协同工作,在可接受的时延内完成密文推理。

2. 先把 HE 的关键设计搞清楚

2.1 四种常见 HE 方案怎么选

在实际落地时,首先要分清底层使用哪种 HE 方案。不同方案在数据编码、计算深度、性能偏好上差异很大。

方案支持的密文运算适合的数据类型常见用途
BGV/BFV加法、乘法整数、有限域元素离散特征、规则引擎、整数运算
CKKS加法、乘法浮点数、复向量水平联邦学习、矩阵运算、AI 推理
TFHE加法、二进制门电路布尔值、整数位电路安全比较、查表、逻辑分支
Paillier加法整数聚合统计、求和场景

需要注意,BGV/BFV 和 CKKS 都支持“批量编码”。BFV 适合把多个整数打包进同一个明文多项式,CKKS 则适合把浮点向量批量编码后执行 SIMD 风格运算。神经网络的权重和特征图非常适合用向量打包表示,所以 CKKS 方案在 AI 推理研究中更常见。

2.2 编码、加密、计算与解码链路

一个 HE 推理系统通常不会直接把“人类可读的权重”送去加密,而是先经过编码器转换为同态明文结构,再进行加密。

基本的计算链路如下:

  1. 将明文数值编码到多项式环或向量槽位;
  2. 用公钥加密为密文;
  3. 在密文上执行加减乘等运算;
  4. 必要时执行重线性化,降低密文大小和噪声;
  5. 将结果返回给持有私钥的一方;
  6. 解密后得到明文结果。

对开发者来说,最容易踩坑的地方是“编码”而不是“加密”。例如 BFV 使用整数模 t 表示明文,超过 t/2 的负数会被映射成模 t 的大整数。若计算中间结果溢出明文模数,解密结果会发生回绕,程序不一定报错,但数值会完全错误。

2.3 噪声增长是绕不开的工程限制

可以把 HE 密文理解为“真实数据 + 一层随机噪声”。每次乘法都会让噪声显著增长,当噪声超过阈值,解密时无法取出原始信号。

因此,全同态加密在执行一轮深层计算时,还需要做两件事:

  • 重线性化:把乘法后膨胀的三元素密文压缩回两元素,控制密文膨胀。
  • 模数切换:通过降低模数抵消一部分噪声增长,同时也会降低可继续计算的深度。

这也是 HE 推理“按深度设计”的根本原因。由于深度限制,把神经网络的非线性层直接替换成高次多项式并不划算,工程上更倾向于使用低次多项式近似激活函数,或者在客户端解密后完成最终非线性判断。

3. 从 Google 视角看私有 AI 的实用性路径

3.1 想保护的是哪一方的数据

在讨论 Google 或任何企业的同态加密实践前,先要厘清一条容易混淆的边界:同态加密并没有同时保护“模型权重”和“用户输入”两方。

典型的隐私推理有两种模式:

  • 用户输入加密,模型权重明文:服务端用明文权重对密文输入做推理,返回加密结果。重点保护用户查询内容。
  • 模型权重加密,用户输入明文:用户用模型公钥加密自己的输入?不对,这里是保护模型权重,常见于模型分发场景。

由于真正有价值的商业模型通常不直接暴露给用户,业界更常见的“私有 AI”其实是第一种。用户可以把搜索词、图片、文本加密后发给服务端,服务端用公开模型完成一次计算,全程看不到用户输入。

3.2 搜索、推荐与私有信息检索

Google 的很多核心业务都涉及大规模检索。传统搜索场景中,服务端可以通过用户搜索日志优化推荐,但这同时也带来很大的隐私隐患。

如果引入同态加密,一个自然的落地形态是:用户对查询条件做同态加密,服务端在密文上计算“哪些候选文档与查询最匹配”,最后仅返回命中的结果。服务端不知道查询关键词,也不知道最终用户点击了哪一条。这里的检索并不需要复杂的神经网络推理,涉及大量加法和比较运算,是 HE 更容易工程化的场景。

不过必须指出,端到端私有搜索的整体链路远比“计算相似度”复杂。索引结构、Top-K 排序、缓存、个性化模型都可能泄露查询隐私。Google 这类企业的价值,不只是实现一个 HE 算子,而是把搜索系统中不同环节都改造成满足隐私边界的版本。

3.3 神经网络推理的密文化

随着大模型落地,另一个方向是把神经网络的完整推理过程放到同态加密环境中。

对于线性层,例如全连接层和卷积层,HE 可以胜任,因为本质是乘法和累加。但对于 ReLU、MaxPool、Softmax 这样的非线性操作,HE 很难直接执行。目前常见做法有两种:

  • 使用多项式近似激活函数,例如用低阶多项式拟合 ReLU;
  • 引入 TFHE 的查表能力,把非线性函数以密文查找表方式实现。

大模型的注意力机制包含 Softmax 以及大量的归一化计算,在密文上执行会消耗极深的乘法预算。因此,当前研究往往停留在“中等规模模型”或“推理切分”层面,把一块可以密文计算的部分放入 HE,其余部分留在明文或可信边界内。

3.4 为什么现在“开始变实用”

很多人关注到 Google 这条新闻,是因为技术信号变了。近年的变化主要体现在几个方面:

  • 硬件加速:GPU、FPGA 和专用加速器开始针对大整数乘法、NTT 变换做优化;
  • 编译工具链:出现了从高级语言到 FHE 电路的转译方案,降低了开发门槛;
  • 模型量化:把浮点网络改成低比特整数网络,使得 BFV 这类整数方案有机会参与推理;
  • 编码封装:成熟开源库把多项式、密钥、噪声控制封装成高度抽象 API,普通后端开发不需要从头读懂数论。

所以,让私有 AI 变得“实用”,是一个系统工程问题,密码学只是其中一个基础组件。真正的突破点是算子编译、模型压缩、密钥调度和硬件协同。

4. 手把手:用 Python 实现一个 HE“私有推理”Demo

前面解读了纸上原理,下面回到代码。这段演示的目标不是复现 Google 的生产系统,而是让你在本地搭建一个小型同态加密运算示例,直观理解“密文乘积 -> 解密得到明文结果”的过程。

4.1 环境准备

本文以 Ubuntu 22.04 或 macOS 环境为例,Python 环境中需要安装 Pyfhel。

Pyfhel 是基于微软 SEAL 的 Python 封装,支持 BFV/BGV/CKKS 等方案。它比较适合用来学习 HE 的工程接口。

pip install pyfhel

如果你更熟悉 OpenMined 系列,也可以参考 TenSEAL:

pip install tenseal

需要说明的是,不同同态加密库的 API 迭代速度较快。建议先按本文思路理解完整流程,再根据自己所使用的库版本调整上下文参数。

4.2 验证两个整数在密文域相乘

我们先把一个乘法的链路跑通。BFV 模式适合加密整数,先建立一个 BFV 上下文,生成公钥、私钥和重线性化密钥。

from Pyfhel import Pyfhel # 1. 初始化 BFV 上下文 HE = Pyfhel() HE.contextGen(scheme="bfv", n=4096, t=1032193) # 2. 生成密钥 HE.keyGen() HE.relinKeyGen() # 3. 明文数据 x = 7 w = 9 # 4. 加密 enc_x = HE.encryptInt(x) enc_w = HE.encryptInt(w) # 5. 密文乘法 enc_result = HE.mult(enc_x, enc_w) enc_result = HE.relin(enc_result) # 6. 解密 result = HE.decryptInt(enc_result) print("明文期望结果:", x * w) print("密文解密结果:", result)

这段代码的运行结果会打印相同的 63。你可能会觉得这显得很基础,但它揭示了关键一点:只要密文乘法能正确工作,我们就能把神经网络中的权重乘法迁移到同态加密域。

这里要强调一个细节:密码学乘法之后,需要调用relinKeyGen()并执行relin()。如果没有生成重线性化密钥,密文会膨胀,后续计算性能会快速劣化。如果示例库 API 有差异,请优先查找你当前版本文档中的relin方法。

4.3 实现一个简单的加密线性推理

一个神经元的前向计算可以表示为:

z = w1 * x1 + w2 * x2 + b

如果 x1、x2 来自用户,w1、w2 和 b 是服务端模型的参数,那么我们可以让用户加密 x1 和 x2,服务端在密文上完成乘加,再返回加密结果。

为了模拟真实架构,我们构造三个角色:

  • 客户端:持有私钥,加密输入,解密最终结果;
  • 服务端:只持有公钥和模型权重,在密文上执行z = w1*x1 + w2*x2 + b
  • 模型权重:明文存储在服务端。

按照明文计算,先写一个对照版本:

def plain_inference(x1, x2): w1 = 3 w2 = 5 b = 1 return w1 * x1 + w2 * x2 + b print(plain_inference(4, 6))

明文结果是3*4 + 5*6 + 1 = 43

接下来是加密推理版本。客户端加密输入后,把两个密文发送给服务端;服务端把模型权重作为明文乘进去。

def encrypted_inference_demo(): # 服务端可公开的模型参数 w1 = 3 w2 = 5 b = 1 # 初始化上下文与密钥,实际中客户端完成 HE = Pyfhel() HE.contextGen(scheme="bfv", n=4096, t=1032193) HE.keyGen() HE.relinKeyGen() # 客户端明文输入 x1 = 4 x2 = 6 # 客户端加密输入 enc_x1 = HE.encryptInt(x1) enc_x2 = HE.encryptInt(x2) # 服务端:密文与明文权重乘法 enc_t1 = HE.mult(enc_x1, HE.encryptInt(w1)) enc_t2 = HE.mult(enc_x2, HE.encryptInt(w2)) enc_t1 = HE.relin(enc_t1) enc_t2 = HE.relin(enc_t2) # 服务端:累加 enc_z = HE.add(enc_t1, enc_t2) enc_z = HE.add(enc_z, HE.encryptInt(b)) # 客户端解密 z = HE.decryptInt(enc_z) return z

注意,这里的w1也执行了encryptInt。严格来说,明文权重并不需要加密,可以直接使用“明文乘法”。许多库也提供了明文乘法接口。为了把链路写清楚,例子中先加密权重,服务端看到的是一个无法解密的权重密文。

实际部署中要权衡的是权限模型:

  • 如果把权重加密后发给服务端,服务端无法直接使用权重做检索或调试,但它也不会泄露模型明文;
  • 如果权重明文放在服务端,那服务端有机会复制权重,这时“隐私”主要保护的是用户查询本身。

4.4 把流程抽象成类

业务代码不适合把 HE 上下文、密钥生成和推理逻辑全部揉在一起。我们把上面的思路整理成一个简单的PrivateInferenceService

class PrivateInferenceService: def __init__(self, weight1, weight2, bias): self.w1 = weight1 self.w2 = weight2 self.b = bias def predict_encrypted(self, enc_x1, enc_x2): # 该接口位于服务端,无法看到明文 x1、x2 enc_t1 = self.he.mult(enc_x1, self.he.encryptInt(self.w1)) enc_t2 = self.he.mult(enc_x2, self.he.encryptInt(self.w2)) enc_t1 = self.he.relin(enc_t1) enc_t2 = self.he.relin(enc_t2) enc_z = self.he.add(enc_t1, enc_t2) enc_z = self.he.add(enc_z, self.he.encryptInt(self.b)) return enc_z

在这个抽象中,he实例必须在服务端初始化,客户端和服务端共享同一套 BFV 上下文参数。生产环境不会直接把私钥暴露在服务端,服务端只持有公钥和重线性化密钥。这里为了演示方便,把加密和解密放到同一个进程里,真实项目需要拆成两个进程或两台机器。

4.5 预期输出与运行说明

当你运行上面的方法时,最终解密输出应该是:

明文推理结果:43 密文推理结果:43

这里能看到“密文参与计算但结果保持一致”。如果选择小明文模数t=65537,模型参数又比较大,多次乘法后可能出现回绕错误。遇到结果诡异时,优先检查是否超过了明文模数范围。

5. 常见问题与排查思路

5.1 为什么解密结果变成了模数回绕后的数值

同态加密的明文空间是一个有限域,所有运算都基于模 t。如果计算中出现了超过模数一半的正数,解密结果可能变成一个看起来毫无关系的大整数。

问题现象常见原因解决思路
解密结果比预期大很多明文溢出模 t换更大的明文模数,或者把参数取模后运算
小规模乘法正常,多次累加后异常噪声累计超过阈值调用重线性化并检查乘法深度
只有第一种参数能正常解密BFV vs CKKS 编码方式不同根据数值类型选择 BFV 或 CKKS
同一个 SDK 在另一台机器无法运行编译器、C++ 依赖版本不一致优先使用官方 wheel 或容器运行环境

5.2 我可以把现成的 PyTorch 模型直接改造成 HE 推理吗

不能直接改造。PyTorch 模型默认使用浮点张量,权重和激活是动态图。HE 推理要求所有计算深度预先可知,且非线性函数必须做多项式近似。

建议的改造流程:

  1. 先用 ONNX 或 TorchScript 导出模型计算图;
  2. 统计每一层的算子类别和乘法深度;
  3. 把所有浮点权重量化为低比特整数;
  4. 将 ReLU 等激活替换为多项式近似;
  5. 把计算图转换为密文友好的算子序列;
  6. 使用加密向量或打包编码完成批量推理。

这个流程中每一步都有对应工具,但很难做到“零人工介入”。

5.3 服务端能通过多次提交推理结果反推用户输入吗

能。如果在交互式协议中,用户每次都提交不同输入并拿到解密后的明文结果,那么服务端可以把模型当成一个查询接口,通过多次探测逼近用户输入。同态加密只保护“单次计算的数据不可见”,不解决推理接口的滥用问题。

这也是为什么私有 AI 系统通常还需要增加:

  • 查询频率限制;
  • 结果脱敏;
  • 差分隐私噪声;
  • 访问审计。

5.4 公钥、私钥、重线性化密钥应该怎么管理

同态加密系统里,至少有三种密钥语义容易被混淆:

  • 私钥:只能留在客户端或受信任环境,用于解密;
  • 公钥:任何数据方都可以持有,用于加密数据;
  • 评估公钥:也就是重线性化密钥。它发给服务端,让服务端能够执行乘法后的压缩,但它不会让服务端解密。

在密钥管理上,一个常见误区是把私钥和评估密钥一起发给服务端。要避免这种错误,需要在系统启动前明确密钥用途,并把私钥落盘策略纳入安全审计范围。

6. 最佳实践:把 HE 放进 AI 工程体系

6.1 先定隐私边界,再选加密算法

很多团队一上来就选 CKKS 或生成大密钥,但忽略了一个问题:我们到底要保护谁的数据不被谁看到?

建议先画一张数据流转图,标清:

  • 客户端上送的数据包含什么;
  • 服务端运行的模型权重是否敏感;
  • 返回结果会不会被服务端记录用于日志分析;
  • 是否涉及合规审计下的数据留存义务。

只有明确这些边界,才能判断同态加密用在哪里,哪些地方还需要配合可信执行环境或安全多方计算。

6.2 模型和推理策略要按 HE 的特性重新设计

HE 并不适合原封不动部署一个大模型。应用层可以做的优化非常多:

  • 把模型权重量化到 8bit 或 16bit,使 BFV 整数运算效率更高;
  • 将激活函数换成低阶多项式,避免高次乘法消耗噪声预算;
  • 把大模型切分成“密文区 + 明文区”,只加密关键隐私层;
  • 使用批处理编码,把多个独立的样本打包进同一个密文,提高吞吐。

最有效的工程经验是“不要在加密域做所有事”,而是把计算图中最适合 HE 的算子挑出来,让传统安全模块处理其余部分。

6.3 使用容器化封装时注意密钥注入方式

把 HE 服务部署成微服务时,要避免把私钥环境变量直接写死在镜像或应用配置里。推荐使用独立密钥管理系统分发密钥,让每个推理实例只拿到当前任务所需的最小权限。

# 不建议 ENV HE_PRIVATE_KEY="..." # 建议 # 在部署编排平台中通过 secret 挂载注入

6.4 性能和安全需要分级评估

同态加密的“安全性”通常由底层密码学方案参数决定,例如多项式阶数 n、明文模数 t、安全强度 bit。参数越大越安全,但性能也会急剧下降。

上线前建议做一组基准测试表,记录不同参数下的执行时间,而不是只跑单条数据就下结论。一个可参考的性能维度:

上下文参数单次乘法耗时可推理的最大层数内存峰值适用场景
n=2048,t 较小教学、原型验证
n=4096,中等 t较慢小型线性模型
n=8192,大 t更深的多层神经网络

这些数据会因为机器、库版本而明显变化,建议用脚本自动化测量,避免随手估算。

6.5 从最小可行性开始,不要首次上线就追求全密文推理

真正做私有 AI 项目的经验是:先跑通一个明文等价系统,把 HE 当做一个独立的计算后端替换部分接口,保证接口返回格式不变,再逐步扩大密文覆盖范围。这样既能验证业务效果,也便于定位是密码学参数问题还是模型结构问题。

7. 下一步可以学什么

回到最初的问题:Google 正在让私有 AI 变成工程现实,但这不是靠一个算法就能完成的事。同态加密只解决了“密文可计算”的基础能力,真正让它在业务中跑起来,还需要模型量化、计算图编译、硬件加速、密钥治理和隐私评估的联合投入。

如果你想继续深入,建议从下面几个方向依次实践:

  1. 阅读 Microsoft SEAL、OpenFHE、Pyfhel 等开源项目的示例代码,重点理解 BFV 与 CKKS 编码差异;
  2. 把一个简单的单层感知机改造成 HE 推理并测量性能;
  3. 用一个公开模型,把 ReLU 替换为低阶多项式,观察精度下降程度;
  4. 实验批处理编码,一次加密多个样本并计算推理;
  5. 尝试把 HE 推理包装成 REST 接口,打通客户端加密到服务端推理的完整链路。

HE 的门槛主要在跨领域,你需要同时理解密码学参数、模型算子、后端部署和安全审计。建议不要一开始就啃复杂的数论公式,而是用上面这种可运行 Demo 建立直觉,再逐渐往底层研究。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询