隐语实现PIR介绍
隐匿查询(Private Information Retrieval PIR)
用户查询服务端数据库中的数据但服务端不知道用户查询的是哪些数据
分类:
按服务器数量分类:
-
单服务器方案(Single Server)
-
多服务器方案(Multi-Server)
按查询类型分类:
-
index PIR
-
Keyword PIR
隐语目前支持的PIR方式:
-
Single server Index PIR : SealPlR
-
Single Server Keyword PIR: Labeled PSI
PIR调用接口:pir_setup
pir_setup 数据预处理,参数说明:
-
input_path:服务端数据文件路径,建议绝对路径
-
key_columns:Key对应的列名
-
label_columns:Label对应的列名,多列,用逗号分隔
-
oprf_key_path::服务端ecc密钥文件,32B,二进制文件
-
mum_per_query:每次查询的id数量
-
label_max_len:Label数据拼接后填充到固定的长度大小
reports=spu.pir_setup(
server='bob',
input_path='/path/B_PIR_DATA.csv',
key_columns='id',
label_columns=['register_date','age'],
oprf_key_path='/path/oprf_key.bin',
setup_path='/path/setup_path',
num_per_query=1,
label_max_len=18,
)
pir_setup 单方任务: 可以使用的secretflow单机模拟配置,或者直接调用spu的python接口
PIR调用接口:pir_query
pir_query双方执行查询任务,参数说明:
-
客户端配置
-
input_path:查询id对应的csv文件路径
-
Key_columns:Key对应的列名
-
output_pathPIR:查询结果输出的文件路径
-
-
服务端配置
-
oprf_key_path:服务端ecc密钥文件,32B,二进制文件
-
setup_path:预处理阶段结果输出路径
-
# client
alice_config ={
'input_path': '/path/A_PIR ID.CSV',
"key _columns': 'id',
'output_path': '/path/sf_pir_out.csv'
# server
bob_config ={
'oprf_key_path': '/path/oprf _key.bin',
'setup_path': '/path/setup_path',
query_config ={
alice: alice_config,
bob: bob_config,
reports = spu.pir query(
server='bob',
config=query_config
)
Index PIR-SealPIR
BFV方案介绍
基于同台密码实现Index PIR的基本原理
SealPIR:
-
多个数据pack到一个HE Plaintext
-
查询的db index转换为plaintext index
-
-
查询向量压缩到一个密文
-
显著减少通信量,server端可通过计算expand得到查询密文向量
-
-
支持多维查询
-
2维查询将数据转换为√n*√n的矩阵,减少expand计算量
-
-
支持多个查询
-
使用cuckoo hash支持同时进行多个查询
-
SealPIR 中给出了通过cuckooHash进行多个查询的算法,可以提高查询效率。cuckooHash选取3个hash,bin的个数为1.5k,具体算法,如下:
server setup 对DB中n个元素,分别计算cuckooHash的3个Hash,得到3个binindex,插入到3个bin index中 client query 将k个查询,通过cuckooHash插入到b=1.5k个bin中,对空的bin进行随机填充
执行每个bin执行一个PIR,共计b个PIR。
Keyword PIR-Labeled PSI
基本原理
核心思想:点值表示得到插值多项式系数表示
隐语label Psl的主要工作
-
以微软的开源代码功能为核心
-
OPRF采用隐语的实现:
-
支持的ecc曲线包括:FourQ,Secp256k1,SM2
-
-
Label的自动填充
-
增加了服务的预处理结果保存功能
-
可以支持离线和查询(多次)两个阶段
-
服务器预处理阶段(setup)
-
选择参数
-
对id数据进行prf计算,前128bit根据截取用于匹配,后128bit作为对称算法密钥加密label
-
根据prf前128bit将数据插入Simple Hash
-
对Simple Hash每一行分别划分bin bundle,并计算matching polynomial和label polynomial
-
将插值多项式系统packing到同态算法明文
客户端和服务器端(query)阶段
-
请求参数
-
执行oprf协议
-
计算查询值的同态密文幂集合
-
使用同态私钥解密服务端返回的同态密文
-
满足匹配条件时,使用oprf的后128bit解密得到label
Label PSI主要参数
PIR测试
初始化Secretflow
与PSI一样,获取未占用的端口
import socket
from contextlib import closing
from typing import cast
def unused_tcp_port() ->int:
with closing(socket.socket(socket.AF_INET,socket.SOCK_STREAM)) as sock:
sock.bind(('',0))
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
return cast(int,sock.getsockname()[1])
print(unused_tcp_port())
alice单独执行:
import secretflow as sf
cluster_config={
'parties':{
'alice':{
'address':'alice:38635',
'listen_addr':'0.0.0.0:38635'
},
'bob':{
'address':'bob:52969',
'listen_addr':'0.0.0.0:52969'
},
},
'self_party':'alice'
}
sf.shutdown()
sf.init(address='local',cluster_config=cluster_config)
bob单独执行:
import secretflow as sf
cluster_config={
'parties':{
'alice':{
'address':'alice:38635',
'listen_addr':'0.0.0.0:38635'
},
'bob':{
'address':'bob:52969',
'listen_addr':'0.0.0.0:52969'
},
},
'self_party':'bob'
}
sf.shutdown()
sf.init(address='local',cluster_config=cluster_config)
初始化SPU
import spu
cluster_def ={
'nodes':[
{
'party':'alice',
'address':'alice:38635',#新空闲端口
},
{
'party':'bob',
'address':'bob:52969',#新空闲端口
},
],
'runtime_config':{
'protocol':spu.spu_pb2.SEMI2K,
'field':spu.spu_pb2.FM128,
},
}
spu=sf.SPU(
cluster_def,
link_desc={
'connect_retry_times':60,
'connect_retry_interval_ms':1000,
},
)
建立索引
spu.pir_setup(
server='alice',
input_path=f"{str(Path.home)}/workshop/alice/payment.csv",
key_columns=['uid'],
label_columns=['credit_card_number','credict_card_provider'],
oprf_key_path=f"{str(Path.home)}/alice_orpf_key",
setup_path=f"{str(Path.home)}/workshop/alice/alice_setup",
num_per_query=1,
label_max_len=20,
bucket_size=1000000
)
对指定目录文件的查询
from pathlib import Path
spu.pir_query(
server='alice',
client='bob',
server_setup_path=f"{str(Path.home)}/workshop/pir_server_setup",
client_key_columns=['uid'],
client_input_path=f"{str(Path.home)}/workshop/bob/pir_query.csv",
client_output_path=f"{str(Path.home)}/workshop/bob/pir_outputcsv",
)