多方安全计算库:MP-SPDZ 与 SEAL 的应用
bash sudo apt update sudo apt install -y automake build-essential cmake git libboost-all-dev libssl-dev libsodium-dev libtool git clone https://github.com/data61/MP-SPDZ.git cd MP-SPDZ make -j8 setup
编译完成后,会生成虚拟机和各种协议的脚本。可通过 `./compile.py` 编译程序,使用 `Scripts/<protocol>.sh` 执行。
### 编写第一个 MPC 程序
MP-SPDZ 的程序使用 `.mpc` 后缀,语法为 Python 子集。例如,实现三方安全计算两个整数相加:
```python
# add.mpc
a = sint.get_input_from(0)
b = sint.get_input_from(1)
c = a + b
print_ln_to(2, 'result = %s', c.reveal_to(2))
解释:sint 是安全整数类型,get_input_from(i) 表示参与者 i 提供私密输入。计算结果 c 仅向参与者 2 揭示。
编译与运行(以半诚实 Shamir 协议为例):
./compile.py -B 32 add
Scripts/shamir.sh add
-B 32 指定环为 32 比特,shamir.sh 自动在本机模拟三个参与方。输出会显示 result = <correct_sum>。
常用操作速查
# 基础运算
x + y, x - y, x * y, x / y # 安全四则运算
x < y, x == y # 比较,返回 sint 布尔值
sint.conv() # 类型转换
Array(10, sint) # 安全数组
# 控制流
if_then(condition) # 条件分支
for_range(loop_var) # 循环
# 输入与输出
x.get_input_from(party_id) # 私密输入
x.reveal_to(party_id) # 向指定方揭示
print_ln_to(party_id, ...) # 打印明文值
自定义协议与性能调优
通过修改 Scripts/<protocol>.sh 中的参数(如 -N 参与方数,-t 腐化阈值,-R 环尺寸)可适配不同安全场景。需要更高性能时,可以选择诚实多数协议(如 replicated-ring.sh),并配合预处理离线阶段优化。
Microsoft SEAL:全同态加密的核心工具
简介
与通用MPC不同,全同态加密(Fully Homomorphic Encryption,FHE)允许直接对密文进行任意计算,解密后结果等同于对明文直接计算的结果。SEAL 是微软研究院开发的 C++ FHE 库,也提供 C# 封装,以其易于使用、文档齐全、性能优异而广受欢迎,尤其适用于“客户端加密、服务端计算”的隐私计算场景。
核心概念
- BFV 方案:针对整数算术,支持向量化打包(Batch Encoding)。适合整数加法、乘法主导的计算。
- CKKS 方案:支持近似浮点数运算,可以处理实数,非常适合机器学习推理等场景。
- 密文类型:
Ciphertext,Plaintext - 密钥:
SecretKey(私钥)、PublicKey(公钥)、RelinKeys(重线性化密钥)、GaloisKeys(旋转密钥)等。
安装 SEAL(Python 版本)
SEAL 的 Python 封装 seal 已发布在 PyPI,安装非常简单:
pip install seal
如果需要 C++ 版本,可从 GitHub 构建,但 Python API 是快速体验的最佳途径。
BFV 示例:加密整数运算
以下代码演示了如何加密两个整数,在密文状态下求和与乘积,然后解密验证。
import seal
# 初始化上下文
parms = seal.EncryptionParameters(seal.scheme_type.bfv)
poly_mod = 8192
parms.set_poly_modulus_degree(poly_mod)
parms.set_coeff_modulus(seal.CoeffModulus.BFVDefault(poly_mod))
parms.set_plain_modulus(1024)
context = seal.SEALContext.Create(parms)
# 密钥生成
keygen = seal.KeyGenerator(context)
public_key = keygen.public_key()
secret_key = keygen.secret_key()
relin_keys = keygen.relin_keys()
# 加密器与运算器
encryptor = seal.Encryptor(context, public_key)
evaluator = seal.Evaluator(context)
decryptor = seal.Decryptor(context, secret_key)
# 加密数值 15 和 30
x_plain = seal.Plaintext("15")
y_plain = seal.Plaintext("30")
x_enc = seal.Ciphertext()
y_enc = seal.Ciphertext()
encryptor.encrypt(x_plain, x_enc)
encryptor.encrypt(y_plain, y_enc)
# 同态加法和乘法
sum_enc = seal.Ciphertext()
evaluator.add(x_enc, y_enc, sum_enc) # 15 + 30 = 45
prod_enc = seal.Ciphertext()
evaluator.multiply(x_enc, y_enc, prod_enc)
evaluator.relinearize_inplace(prod_enc, relin_keys) # 乘法后重线性化
# 解密
plain_result = seal.Plaintext()
decryptor.decrypt(sum_enc, plain_result)
print("Sum:", plain_result.to_string()) # 输出 45
decryptor.decrypt(prod_enc, plain_result)
print("Product:", plain_result.to_string()) # 输出 450
CKKS 示例:实数近似计算
CKKS 常用于保留精度的浮点运算。设置时不需要明文模数,改为配置 scale。
parms = seal.EncryptionParameters(seal.scheme_type.ckks)
parms.set_poly_modulus_degree(8192)
parms.set_coeff_modulus(seal.CoeffModulus.Create(8192, [60, 40, 40, 60]))
scale = pow(2.0, 40)
context = seal.SEALContext.Create(parms)
keygen = seal.KeyGenerator(context)
encryptor = seal.Encryptor(context, keygen.public_key())
evaluator = seal.Evaluator(context)
decryptor = seal.Decryptor(context, keygen.secret_key())
encoder = seal.CKKSEncoder(context)
relin_keys = keygen.relin_keys()
# 编码与加密
x = [1.5, 2.3]
x_plain = seal.Plaintext()
encoder.encode(x, scale, x_plain)
x_enc = seal.Ciphertext()
encryptor.encrypt(x_plain, x_enc)
# 同态平方
x_sq = seal.Ciphertext()
evaluator.square(x_enc, x_sq)
evaluator.relinearize_inplace(x_sq, relin_keys)
# 解密与解码
dec = seal.Plaintext()
decryptor.decrypt(x_sq, dec)
result = encoder.decode_double(dec)
print("x^2:", result) # 接近 [2.25, 5.29]