把加密数据交给云服务商计算,但不给它解密密钥——这在传统密码学里不可能,但同态加密做到了。医院把加密的患者数据发给 AI 公司做模型训练,AI 公司只能拿到密文,训练结果也是密文,只有医院用私钥解密后才能看到结果。**同态加密(Homomorphic Encryption, HE)**允许在密文上执行加法和乘法运算,解密后的结果与明文运算结果一致。这不是魔法,是格密码学的数学保证。
一、同态加密基础
1.1 什么是同态加密?
同态加密(Homomorphic Encryption, HE)允许在密文上直接进行计算,解密后的结果等于在明文上计算的结果:
Enc(a) + Enc(b) = Enc(a + b) # 加法同态Enc(a) × Enc(b) = Enc(a × b) # 乘法同态用一个具体的例子来理解:假设你有一组加密的工资数据 Enc(5000), Enc(6000), Enc(7000),你想计算平均工资。传统方式必须先解密再计算,而同态加密允许你直接在密文上做加法,得到 Enc(18000),然后除以 3 得到 Enc(6000)。你只持有私钥,可以解密得到 6000——但计算服务器全程看不到任何明文。
1.2 同态加密的分类
| 类型 | 支持运算 | 代表方案 | 性能 |
|---|---|---|---|
| 半同态(PHE) | 加法或乘法之一 | Paillier(加法)、RSA(乘法) | 快 |
| 某种程度同态(SWHE) | 有限次加法+乘法 | ElGamal | 中 |
| 全同态(FHE) | 任意次加法+乘法 | CKKS、BFV、BGV | 慢 |
1.3 三种类型深入对比
| 维度 | 半同态(PHE) | 某种程度同态(SWHE) | 全同态(FHE) |
|---|---|---|---|
| 加法 | (Paillier) | ||
| 乘法 | (RSA) | (有限次) | (任意次) |
| 比较运算 | (通过编码) | ||
| 计算深度 | 无限(单运算) | 有限(噪声限制) | 无限(自举) |
| 密文膨胀 | 2-4x | 10-100x | 100-10000x |
| 性能 | 接近明文 | 慢 100-1000x | 慢 10000-1000000x |
| 实用性 | 生产可用 | 特定场景 | 研究为主,逐步实用 |
| 典型应用 | 电子投票、聚合统计 | 简单电路 | 机器学习推理 |
全同态加密的”全”是指理论上支持任意计算,但实际中性能约束使得复杂计算仍然不现实。2024 年的 FHE 加密操作比明文慢 4-6 个数量级,这意味着一个明文 1 秒的计算在 FHE 下可能需要数天。不过,对于特定场景(如简单推理、聚合统计),FHE 已经可以实用。
二、全同态加密方案
2.1 BFV 方案(整数运算)
BFV 适合精确整数计算:
# Python: 使用 TenSEAL 进行 BFV 同态加密import tenseal as ts
# 创建 BFV 上下文context = ts.context(ts.SCHEME_TYPE.BFV, poly_modulus_degree=4096, plain_modulus=1032193)
# 加密plain_a = ts.bfv_vector(context, [1, 2, 3, 4])plain_b = ts.bfv_vector(context, [5, 6, 7, 8])enc_a = plain_a.encrypt()enc_b = plain_b.encrypt()
# 密文计算enc_sum = enc_a + enc_b # 加法enc_prod = enc_a * enc_b # 乘法
# 解密result_sum = enc_sum.decrypt()result_prod = enc_prod.decrypt()BFV 的核心参数:
| 参数 | 说明 | 典型值 | 影响 |
|---|---|---|---|
poly_modulus_degree | 多项式模数度数 N | 4096/8192/16384 | 越大越安全但越慢 |
plain_modulus | 明文模数 t | 1032193 | 控制明文空间大小 |
coeff_modulus | 系数模数链 | 自动生成 | 控制噪声预算 |
BFV 的噪声管理:每次乘法都会增加密文中的噪声。当噪声超过阈值时,解密结果会出错。poly_modulus_degree 越大,能容纳的乘法深度越深。
2.2 CKKS 方案(近似计算)
CKKS 适合浮点数近似计算(机器学习场景):
# CKKS 同态加密context = ts.context(ts.SCHEME_TYPE.CKKS, poly_modulus_degree=8192, coeff_mod_bit_sizes=[60, 40, 40, 60])context.global_scale = 2**40
# 加密浮点数enc_a = ts.ckks_vector(context, [1.5, 2.3, 3.7])enc_b = ts.ckks_vector(context, [4.2, 5.1, 6.8])
# 密文计算enc_sum = enc_a + enc_benc_prod = enc_a * enc_b
# 解密(近似值)print(enc_sum.decrypt()) # [5.7, 7.4, 10.5]| 方案 | 数据类型 | 精度 | 适用场景 |
|---|---|---|---|
| BFV | 整数 | 精确 | 投票统计、数据库查询 |
| BGV | 整数 | 精确 | 通用整数计算 |
| CKKS | 浮点数 | 近似 | 机器学习、统计分析 |
2.3 BFV vs BGV vs CKKS 深入对比
| 维度 | BFV | BGV | CKKS |
|---|---|---|---|
| 明文空间 | 整数模 t | 整数模 t | 实数(编码后) |
| 精度 | 精确 | 精确 | 近似(可控误差) |
| 噪声管理 | 模切换 | 模切换 | 重缩放(Rescale) |
| 自举效率 | 中 | 中 | 高(CKKS 自举更高效) |
| 乘法深度 | 受 plain_modulus 限制 | 受模链长度限制 | 受缩放因子限制 |
| 典型参数 | N=4096, t=1032193 | N=8192, 模链=[60,40,40,60] | N=8192, scale=2^40 |
| 最佳场景 | 精确整数运算 | 通用整数运算 | 浮点/ML 推理 |
| 实现库 | SEAL/TenSEAL | HElib | SEAL/TenSEAL |
CKKS 为什么适合机器学习?
机器学习的核心运算是矩阵乘法和激活函数。CKKS 的优势在于:
- 浮点数编码:CKKS 可以将多个浮点数打包到一个密文中(SIMD 编码),一次操作处理多个数据
- 近似计算可接受:神经网络本身就有浮点误差,CKKS 的近似误差在可接受范围内
- 高效自举:CKKS 的自举过程比 BFV/BGV 更高效,支持更深的计算电路
2.4 自举(Bootstrapping):FHE 的关键技术
自举是 Gentry 在 2009 年提出的突破性技术,它让全同态加密成为可能。核心思想是:在密文上同态地执行解密函数,从而”刷新”噪声。
自举的代价是巨大的性能开销——一次自举可能比普通乘法慢 100-1000 倍。因此实际应用中,设计 FHE 电路时要尽量减少自举次数。
三、Microsoft SEAL 实战
3.1 SEAL 简介
Microsoft SEAL 是目前最成熟的开源 FHE 库,支持 BFV 和 CKKS 两种方案。它由微软研究院开发,被广泛用于学术研究和工业原型。
3.2 SEAL BFV 示例:加密整数运算
// C++: Microsoft SEAL BFV 示例#include <seal/seal.h>using namespace seal;
// 1. 设置加密参数EncryptionParameters params(scheme_type::bfv);size_t poly_modulus_degree = 4096;params.set_poly_modulus_degree(poly_modulus_degree);params.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree));params.set_plain_modulus(PlainModulus::Batching(poly_modulus_degree, 20));
// 2. 创建上下文SEALContext context(params);
// 3. 生成密钥KeyGenerator keygen(context);SecretKey secret_key = keygen.secret_key();PublicKey public_key;keygen.create_public_key(public_key);RelinKeys relin_keys;keygen.create_relin_keys(relin_keys);GaloisKeys galos_keys;keygen.create_galois_keys(galos_keys);
// 4. 加密Encryptor encryptor(context, public_key);Evaluator evaluator(context);Decryptor decryptor(context, secret_key);
// 加密两个整数Plaintext plain_a("42");Plaintext plain_b("17");Ciphertext enc_a, enc_b;encryptor.encrypt(plain_a, enc_a);encryptor.encrypt(plain_b, enc_b);
// 5. 同态计算Ciphertext enc_sum;evaluator.add(enc_a, enc_b, enc_sum); // 加法: Enc(42 + 17)
Ciphertext enc_prod;evaluator.multiply(enc_a, enc_b, enc_prod); // 乘法: Enc(42 * 17)evaluator.relinearize_inplace(enc_prod, relin_keys); // 重线性化
// 6. 解密Plaintext plain_sum, plain_prod;decryptor.decrypt(enc_sum, plain_sum);decryptor.decrypt(enc_prod, plain_prod);std::cout << "Sum: " << plain_sum.to_string() << std::endl; // 59std::cout << "Prod: " << plain_prod.to_string() << std::endl; // 7143.3 SEAL CKKS 示例:加密浮点运算
// C++: Microsoft SEAL CKKS 示例 — 浮点数向量运算#include <seal/seal.h>using namespace seal;
// 1. 设置 CKKS 参数EncryptionParameters params(scheme_type::ckks);size_t poly_modulus_degree = 8192;params.set_poly_modulus_degree(poly_modulus_degree);params.set_coeff_modulus(CoeffModulus::Create( poly_modulus_degree, {60, 40, 40, 40, 60}));
SEALContext context(params);
// 2. 密钥生成KeyGenerator keygen(context);auto secret_key = keygen.secret_key();PublicKey public_key;keygen.create_public_key(public_key);RelinKeys relin_keys;keygen.create_relin_keys(relin_keys);GaloisKeys galois_keys;keygen.create_galois_keys(galois_keys);
Encryptor encryptor(context, public_key);Evaluator evaluator(context);Decryptor decryptor(context, secret_key);CKKSEncoder encoder(context);
double scale = pow(2.0, 40);
// 3. 编码和加密向量vector<double> input_a = {1.5, 2.3, 3.7, 4.1};vector<double> input_b = {0.5, 1.7, 2.3, 3.9};
Plaintext plain_a, plain_b;encoder.encode(input_a, scale, plain_a);encoder.encode(input_b, scale, plain_b);
Ciphertext enc_a, enc_b;encryptor.encrypt(plain_a, enc_a);encryptor.encrypt(plain_b, enc_b);
// 4. 同态加法Ciphertext enc_sum;evaluator.add(enc_a, enc_b, enc_sum);
// 5. 同态乘法Ciphertext enc_prod;evaluator.multiply(enc_a, enc_b, enc_prod);evaluator.relinearize_inplace(enc_prod, relin_keys);evaluator.rescale_to_next_inplace(enc_prod); // CKKS 重缩放
// 6. 解密和解码Plaintext plain_sum;decryptor.decrypt(enc_sum, plain_sum);vector<double> result_sum;encoder.decode(plain_sum, result_sum);// result_sum ≈ [2.0, 4.0, 6.0, 8.0]
Plaintext plain_prod;decryptor.decrypt(enc_prod, plain_prod);vector<double> result_prod;encoder.decode(plain_prod, result_prod);// result_prod ≈ [0.75, 3.91, 8.51, 15.99]3.4 SEAL 性能基准
以下是在 Intel Xeon E5-1650 上的典型性能数据(SEAL 4.1):
| 操作 | BFV (N=4096) | CKKS (N=8192) | 明文 |
|---|---|---|---|
| 密钥生成 | 12ms | 45ms | — |
| 加密 | 0.8ms | 2.1ms | — |
| 解密 | 0.3ms | 0.8ms | — |
| 加法 | 0.05ms | 0.08ms | ~1ns |
| 乘法 | 3.2ms | 8.5ms | ~1ns |
| 重线性化 | 1.8ms | 4.2ms | — |
| 自举 | — | 150-500ms | — |
| 密文大小 | 32KB | 64KB | 32B |
这些数据仅供参考,实际性能取决于参数选择和硬件。CKKS 自举是最昂贵的操作,一次自举可能需要数百毫秒。设计 FHE 应用时,应尽量减少自举次数——通常通过优化电路深度来实现。
四、应用场景
4.1 隐私计算
| 场景 | 说明 | 方案 |
|---|---|---|
| 医疗数据分析 | 在加密病历上分析 | CKKS |
| 金融风控 | 在加密数据上计算评分 | BFV |
| 联邦学习 | 加密梯度聚合 | CKKS |
| 隐私投票 | 加密计票 | BFV |
4.2 隐私保护机器学习
FHE 在机器学习中最有前景的应用是隐私推理:客户端将数据加密发送给服务器,服务器在密文上运行模型推理,返回加密结果——服务器全程看不到输入数据和推理结果。
# TenSEAL: 隐私保护的逻辑回归推理import tenseal as ts
# 1. 客户端:加密输入特征context = ts.context(ts.SCHEME_TYPE.CKKS, poly_modulus_degree=8192, coeff_mod_bit_sizes=[60, 40, 40, 40, 60])context.global_scale = 2**40context.generate_galois_keys()
features = [0.5, 1.2, 0.8, 2.1, 0.3] # 患者特征enc_features = ts.ckks_vector(context, features)
# 2. 服务器:同态推理(服务器看不到明文)# 模型权重(明文,可以是公开的或加密的)weights = [0.1, -0.3, 0.5, 0.2, -0.1]bias = 0.05
# 线性部分:w·x + benc_score = enc_features.dot(weights) + bias
# 近似 sigmoid(用多项式逼近)# sigmoid(x) ≈ 0.5 + 0.197*x - 0.004*x^3enc_x = enc_scoreenc_x2 = enc_x * enc_xenc_x3 = enc_x2 * enc_xenc_prob = 0.5 + 0.197 * enc_x - 0.004 * enc_x3
# 3. 客户端:解密得到预测概率prob = enc_prob.decrypt()[0]print(f"预测概率: {prob:.4f}") # 例如 0.72314.3 安全投票系统
BFV 同态加密天然适合电子投票——选票加密后可以同态计票,计票方无法看到单个选票内容:
# BFV 安全投票系统import tenseal as ts
# 1. 初始化上下文(选举委员会生成)context = ts.context(ts.SCHEME_TYPE.BFV, poly_modulus_degree=4096, plain_modulus=1032193)
# 2. 每个选民加密自己的选票# 候选人 A=1, B=2, C=3, 弃权=0voter_choices = [1, 2, 1, 3, 1, 2, 1, 0, 3, 1] # 10 位选民
encrypted_votes = []for choice in voter_choices: enc_vote = ts.bfv_vector(context, [choice]).encrypt() encrypted_votes.append(enc_vote)
# 3. 同态计票(计票方看不到单个选票)# 将所有加密选票相加tally = encrypted_votes[0]for vote in encrypted_votes[1:]: tally = tally + vote # 同态加法
# 4. 解密计票结果(需要多个受托方联合解密)result = tally.decrypt()print(f"候选人 A: {result[0].count(1)} 票") # 实际实现需要更复杂的编码4.4 医疗数据隐私分析
# CKKS: 跨医院隐私统计分析import tenseal as ts
# 1. 医院A:加密患者数据context = ts.context(ts.SCHEME_TYPE.CKKS, poly_modulus_degree=8192, coeff_mod_bit_sizes=[60, 40, 40, 40, 60])context.global_scale = 2**40context.generate_galois_keys()
hospital_a_ages = [45, 52, 38, 61, 55, 42, 48, 67, 33, 59]enc_ages_a = ts.ckks_vector(context, hospital_a_ages)
# 2. 医院B:加密患者数据hospital_b_ages = [41, 63, 37, 58, 44, 51, 39, 62, 46, 53]enc_ages_b = ts.ckks_vector(context, hospital_b_ages)
# 3. 研究机构:在密文上计算统计量# 计算总年龄enc_total_a = enc_ages_a.sum() # 同态求和enc_total_b = enc_ages_b.sum()
# 计算平均年龄(近似)count_a = len(hospital_a_ages)count_b = len(hospital_b_ages)
avg_a = enc_total_a.decrypt()[0] / count_aavg_b = enc_total_b.decrypt()[0] / count_bprint(f"医院A平均年龄: {avg_a:.1f}") # 研究机构只看到统计结果print(f"医院B平均年龄: {avg_b:.1f}") # 看不到任何个体数据4.5 性能挑战
| 维度 | 同态加密 | 明文计算 | 差距 |
|---|---|---|---|
| 加密 | 1ms | — | — |
| 加法 | 0.1ms | 1ns | 10万倍 |
| 乘法 | 10ms | 1ns | 1000万倍 |
| 密文大小 | 100KB | 8B | 1万倍 |
4.6 性能优化策略
FHE 的性能瓶颈不是不可优化的。以下是实际项目中常用的优化策略:
| 策略 | 说明 | 加速效果 |
|---|---|---|
| SIMD 打包 | 将多个数据打包到一个密文 | 100-1000x 吞吐量 |
| 电路优化 | 减少乘法深度和自举次数 | 10-100x |
| 算子融合 | 合并连续运算,减少密文操作 | 2-5x |
| 硬件加速 | GPU/FPGA/ASIC 加速 NT | 10-100x |
| 混合方案 | PHE+TEE+MPC 组合 | 视场景而定 |
全同态加密目前的主要瓶颈是性能——比明文计算慢 4-6 个数量级。实际应用中,通常结合半同态加密+安全多方计算+可信执行环境来平衡安全与性能。
五、与其他隐私计算技术对比
5.1 四大隐私计算技术
| 维度 | 同态加密(HE) | 安全多方计算(MPC) | 可信执行环境(TEE) | 差分隐私(DP) |
|---|---|---|---|---|
| 核心思想 | 加密后计算 | 分片计算 | 硬件隔离 | 加噪声保护 |
| 信任假设 | 密码学安全 | 多数方诚实 | 硬件可信 | 统计安全 |
| 计算精度 | 精确/近似 | 精确 | 精确 | 有损(加噪声) |
| 性能 | 极慢 | 慢 | 接近明文 | 快 |
| 安全等级 | 高(可证明安全) | 高(可证明安全) | 中(依赖硬件) | 中(隐私预算) |
| 典型应用 | 隐私推理 | 联合建模 | 数据沙箱 | 统计发布 |
5.2 详细对比
同态加密 vs 安全多方计算(MPC)
MPC 允许多方在不泄露各自输入的情况下共同计算一个函数。与 HE 的关键区别:
| 维度 | HE | MPC |
|---|---|---|
| 参与方 | 单方计算 | 多方协作 |
| 通信开销 | 低(只传密文) | 高(多轮交互) |
| 计算开销 | 极高 | 高 |
| 信任假设 | 服务器不可信 | 多数服务器诚实 |
| 适用场景 | 云端推理 | 联合建模 |
同态加密 vs 可信执行环境(TEE)
TEE(如 Intel SGX、ARM TrustZone)通过硬件隔离保护代码和数据。与 HE 的关键区别:
| 维度 | HE | TEE |
|---|---|---|
| 安全基础 | 数学证明 | 硬件安全 |
| 性能 | 极慢 | 接近明文 |
| 侧信道攻击 | 免疫 | 有风险(缓存/时序攻击) |
| 信任模型 | 不信任硬件 | 信任硬件厂商 |
| 已知攻击 | 无(理论安全) | Foreshadow/Plundervolt/Spectre |
同态加密 vs 差分隐私(DP)
差分隐私通过在查询结果中添加精心校准的噪声来保护个体隐私。与 HE 的关键区别:
| 维度 | HE | DP |
|---|---|---|
| 保护目标 | 数据本身 | 个体在数据中的贡献 |
| 精度 | 精确/近似 | 有损(噪声) |
| 计算结果 | 确定性 | 随机性 |
| 适用场景 | 精确计算 | 统计发布 |
| 组合性 | 无限次查询安全 | 隐私预算递减 |
5.3 混合方案:取长补短
实际系统中,通常组合多种技术来平衡安全与性能:
| 混合方案 | 组合方式 | 适用场景 |
|---|---|---|
| HE + TEE | TEE 做重计算,HE 做轻计算 | 机器学习训练 |
| HE + MPC | HE 做线性层,MPC 做非线性层 | 神经网络推理 |
| HE + DP | HE 计算结果加 DP 噪声 | 统计发布 |
| PHE + MPC | Paillier 做加法,MPC 做比较 | 联邦学习 |
不要执着于”纯 FHE”方案。在实际项目中,混合方案往往是更务实的选择:用 PHE(Paillier)做加法聚合,用 TEE 做复杂计算,用 DP 保护输出隐私。这样可以在安全性和性能之间取得更好的平衡。
六、FHE 开源生态
| 项目 | 语言 | 支持方案 | 特点 |
|---|---|---|---|
| Microsoft SEAL | C++ | BFV, CKKS | 最成熟,微软官方维护 |
| TenSEAL | Python | BFV, CKKS | SEAL 的 Python 绑定,易上手 |
| HElib | C++ | BGV, CKKS | IBM 开发,自举优化好 |
| OpenFHE | C++ | BFV, BGV, CKKS, FHEW, TFHE | 统一 API,多方案支持 |
| Concrete-ML | Python | TFHE | Zama 开发,ML 专用 |
| PALISADE | C++ | BFV, BGV, CKKS | NIST 赞助,模块化设计 |
# OpenFHE: 统一 API 示例(支持多种方案)# pip install openfhe
from openfhe import *
# 1. CKKS 方案设置parameters = CCParamsCKKSRNS()parameters.SetMultiplicativeDepth(5)parameters.SetScalingModSize(50)parameters.SetBatchSize(8)
cc = GenCryptoContext(parameters)cc.Enable(PKESchemeFeature.PKE)cc.Enable(PKESchemeFeature.KEYSWITCH)cc.Enable(PKESchemeFeature.LEVELEDSHE)cc.Enable(PKESchemeFeature.ADVANCEDSHE)
# 2. 密钥生成keys = cc.KeyGen()cc.EvalMultKeyGen(keys.secretKey)cc.EvalSumKeyGen(keys.secretKey)
# 3. 编码加密vec_a = [1.5, 2.3, 3.7, 4.1, 0.5, 1.7, 2.3, 3.9]pt_a = cc.MakeCKKSPackedPlaintext(vec_a)ct_a = cc.Encrypt(keys.publicKey, pt_a)
# 4. 同态计算ct_result = cc.EvalSum(ct_a, 8) # 同态求和
# 5. 解密pt_result = cc.Decrypt(ct_result, keys.secretKey)pt_result.SetLength(1)print(f"Sum: {pt_result.GetRealPackedValue()}") # ≈ 20.0七、总结
上一章建立了密钥管理与 KMS/HSM的认知框架。
| 维度 | 关键要点 |
|---|---|
| 分类 | PHE(加法/乘法)、SWHE(有限次)、FHE(任意次+自举) |
| BFV | 整数精确计算,投票/查询,SEAL/TenSEAL 实现 |
| BGV | 整数精确计算,通用场景,HElib 实现 |
| CKKS | 浮点近似计算,机器学习/统计,SIMD 打包加速 |
| 自举 | FHE 关键技术,同态执行解密函数刷新噪声 |
| 应用 | 隐私推理、安全投票、医疗分析、联邦学习 |
| 混合方案 | HE+TEE/MPC/DP 组合,平衡安全与性能 |
| 挑战 | 性能差距 4-6 个数量级,SIMD+电路优化+硬件加速可缩小 |
支持与分享
如果这篇文章对你有帮助,欢迎支持作者或分享给更多人
部分信息可能已经过时






