隐语 PSI benchmark 白皮书,新鲜出炉
隐语PSI亮点
基于公钥密码的PSI方案,包括:基于判定型密钥交换(Decisional Diffie-Hellman,DDH)的PSI方案和RSA盲签名的PSI方案; 基于不经意传输(Oblivious Transfer,OT)的PSI方案; 基于通用MPC的PSI方案,例如基于混淆电路(Garbled Circuit,GC)的PSI方案; 基于同态加密(Homomorphic Encryption,HE)的PSI方案。
两方PSI:参与方为2个; 多方PSI:参与方>2个。
半诚实模型的PSI; 恶意模型的PSI。
SecretFlow SPU 实现了半诚实模型下的两方和三方PSI协议,密钥安全强度是128bit,统计安全参数是40bit。
两方PSI协议:
基于DDH的PSI(Private Set Intersection)协议
基于DDH的PSI协议先对简单易于理解和实现,依赖的密码技术已被广泛论证,通信量低,但计算量较大。
隐语实现了基于椭圆曲线(Elliptic Curve)群的DDH PSI协议,支持的椭圆曲线类型包括:Curve25519,SM2,Secp256k1。本次benchmark选用的曲线是Curve25519。
基于OT扩展的KKRT16
KKRT16是第一个千万规模(224)求交时间在1分钟之内的PSI方案,通信量较大;
隐语实现了KKRT16协议,并参考了进年来的性能优化和安全改进方案,例如:stash-less CuckooHash,[GKWW20]中 FixedKey AES作为 correlation-robust 哈希函数。
基于PCG的BC22
BC22 PSI依赖的PCG(Pseudorandom Correlation Generator)方案是近年来mpc方向的研究热点,相比KKRT16计算量和通信两方面都有了很大改进,从成本(monetary cost)角度更能满足实际业务需求。PCG实现依赖LPN(Learning Parity with Noise)问题,由于是2022年最新的协议,协议的安全性还需要更多密码专家的分析和论文。
隐语v0.7中实现了BC22 PSI方案,其中的PCG/VOLE使用了emp-zk中的[WYKW21]实现,欢迎大家审查和进一步改进;
三方PSI(Private Set Intersection)协议
基于DDH的三方PSI协议
隐语实现了自研的基于 ECDH 的三方 PSI 协议,注意我们实现的这个协议会泄漏两方交集大小,请自行判断是否满足使用场景的安全性,本次benchmark选用的曲线是Curve25519。
复现方式
一、测试机型环境
Python:3.8 pip: >= 19.3 OS: CentOS 7 CPU/Memory: 推荐最低配置是 8C16G 硬盘:500G
二、安装conda
使用conda管理python环境,如果机器没有conda需要先安装,步骤如下:
#sudo apt-get install wgetwget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh#安装bash Miniconda3-latest-Linux-x86_64.sh# 一直按回车然后输入yesplease answer 'yes' or 'no':>>> yes# 选择安装路径, 文件名前加点号表示隐藏文件Miniconda3 will now be installed into this location:>>> ~/.miniconda3# 添加配置信息到 ~/.bashrc文件Do you wish the installer to initialize Miniconda3 by running conda init? [yes|no][no] >>> yes#运行配置信息文件或重启电脑source ~/.bashrc#测试是否安装成功conda --version
三、安装secretflow
# 创建干净的python环境
conda create -n sf-benchmark python=3.8
# 进入benchmark 环境
conda activate sf-benchmark
# 安装secretflow
pip install -U secretflow
# 创建一个sf-benchmark目录
mkdir sf-benchmark
cd sf-benchmark
1.验证安装是否成功
>>> import secretflow as sf
>>> sf.init(['alice', 'bob', 'carol'], num_cpus=8, log_to_driver=True)
>>> dev = sf.PYU('alice')
>>> import numpy as np
>>> data = dev(np.random.rand)(3, 4)
>>> sf.reveal(data)
四、创建节点并启动集群
1.创建ray header节点
RAY_DISABLE_REMOTE_CODE=true \
ray start --head --node-ip-address="192.168.0.1" --port="9394" --resources='{"alice": 8}' --include-dashboard=False
2.创建从属节点
RAY_DISABLE_REMOTE_CODE=true \
ray start --address="192.168.0.1:9394" --resources='{"bob": 8}'
RAY_DISABLE_REMOTE_CODE=true \
ray start --address="192.168.0.1:9394" --resources='{"carol": 8}'
3.验证节点是否启动
>>> import secretflow as sf
>>> sf.init(address='192.168.0.1:9394')
>>> alice = sf.PYU('alice')
>>> bob = sf.PYU('bob')
>>> sf.reveal(alice(lambda x : x)(2))
>>> sf.reveal(bob(lambda x : x)(2))
4.生成数据
把脚本generate_psi.py:https://github.com/secretflow/spu/blob/main/spu/psi/tools/generate_psi.py传到alice机器的root目录下
执行如下代码
# 生成三份一千万数据
python3 generate_psi.py 10000000
# 生成三份一亿数据
python3 generate_psi.py 100000000
5.限制宽带/延迟
清除限制
查看已有配置
6.Benchmark脚本
支持的PSI协议列表:
ECDH_PSI_2PC
KKRT_PSI_2PC
BC22_PSI_2PC
ECDH_PSI_3PC
import sys
import time
import logging
from absl import app
import spu
import secretflow as sf
# init log
logging.basicConfig(stream=sys.stdout, level=logging.INFO)
# SPU settings
cluster_def = {
'nodes': [
# <<< !!! >>> replace <192.168.0.1:12945> to alice node's local ip & free port
{'party': 'alice', 'id': 'local:0', 'address': '192.168.0.1:12945', 'listen_address': '0.0.0.0:12945'},
# <<< !!! >>> replace <192.168.0.2:12946> to bob node's local ip & free port
{'party': 'bob', 'id': 'local:1', 'address': '192.168.0.2:12946', 'listen_address': '0.0.0.0:12946'},
# <<< !!! >>> if you need 3pc test, please add node here, for example, add carol as rank 2
# {'party': 'carol', 'id': 'local:2', 'address': '127.0.0.1:12347'},
],
'runtime_config': {
'protocol': spu.spu_pb2.SEMI2K,
'field': spu.spu_pb2.FM128,
},
}
def main(_):
# sf init
# <<< !!! >>> replace <192.168.0.1:9394> to your ray head
sf.init(address='192.168.0.1:9394')
alice = sf.PYU('alice')
bob = sf.PYU('bob')
carol = sf.PYU('carol')
# <<< !!! >>> replace path to real parties local file path.
input_path = {
alice: '/data/psi_1.csv',
bob: '/data/psi_2.csv',
# if run with `ECDH_PSI_3PC`, add carol
# carol: '/data/psi_3.csv',
}
output_path = {
alice: '/data/psi_output.csv',
bob: '/data/psi_output.csv',
# if run with `ECDH_PSI_3PC`, add carol
# carol: '/data/psi_output.csv',
}
select_keys = {
alice: ['id'],
bob: ['id'],
# if run with `ECDH_PSI_3PC`, add carol
# carol: ['id'],
}
spu = sf.SPU(cluster_def)
# prepare data
start = time.time()
reports = spu.psi_csv(
key=select_keys,
input_path=input_path,
output_path=output_path,
receiver='alice', # if `broadcast_result=False`, only receiver can get output file.
protocol='KKRT_PSI_2PC', # psi protocol
precheck_input=False, # will cost ext time if set True
sort=False, # will cost ext time if set True
broadcast_result=False, # will cost ext time if set True
)
print(f"psi reports: {reports}")
logging.info(f"cost time: {time.time() - start}")
sf.shutdown()
if __name__ == '__main__':
app.run(main)
五、Benchmark报告
https://github.com/secretflow
https://gitee.com/secretflow
公众号:隐语的小剧场
B站:隐语secretflow
邮箱:secretflow-contact@service.alipay.com